As my question in the subject above states, what requirements do you typically have to meet in order to say "Ok, I need encodeWithCoder: and initWithCoder: instantiation for this"? Typically you can write object state to NSUserDefaults, so I'm curious when do you experts decide to use one vs the other?
NSCoder
is the standard Cocoa method of implementing serialization. See Apple's Archives and Serializations Programming Guide for Cocoa for details.
User defaults is, basically, a property list. Property lists are similar to JSON and can only store specific types of data -- NSString, NSNumber, NSData, NSDate, NSArray, NSDictionary. If you try to store anything else in a user default, you'll get an exception. Property lists also can't handle arbitrary object graphs, only trees.
You could always take your custom state and convert it into a property-list compatible data structure, then store it in user defaults; but then you're basically implementing an object serialization mechanism, and you might as well use the more powerful one that's already provided by NSArchiver.
initWithCoder: is used by the OS when un-archiving XIB files; if you look closely, you'll see that initWithFrame: is not called for views you create in your XIB; they'll have initWithCoder: called instead.
I go with NSCoder whenever I have some sort of complicated data to store that I never have to edit by hand. For example, my app Converter stores currency exchange rates downloaded from the Internet in an NSCoder archive. However, that's the only thing it keeps in such an archive: unit definitions, which are only ever altered by hand, are kept in a series of plist files in the application bundle, and things like the most recently selected units and values are kept in NSUserDefaults.