Sometimes traversing through the life-cycle callbacks of view loading on the iPhone still gives me a headache. Especially when using Interface Builder (IB) as part of the UI development, finding the right method to override in order to get your custom drawing/init/etc. done can be more difficult than it may seem. Recently, I was lost again in the quagmire of methods to choose from when building a custom UIView subclass that provided some basic look-and-feel customization over the standard view structure The answer that was revealed to me is today’s tip.
The commonly recommended place to do custom initialization for custom views is in the
initWithCoder methods. When you are defining parts of your UI in IB,
initWithCoder is the one of these that is called by the nib-loading code. However, it is usually the case that any work done with members declared as IBOutlet are still nil at this point, so your custom changes will fall on deaf ears. This drives many developers to put custom initialization code in the
viewDidLoad method of the view controller…because it works. The problem here is a conceptual one. You are no longer encapsulating all of the custom functionality for your view in the view class, some of the required custom code is leaking out into the controller. You are now relying on code in the custom view’s container to provide some of the needed functionality to properly initialize the view, which makes the code brittle.
awakeFromNib; a UIKit addition to NSObject that receives a message from the nib-loading code after all the outlets and actions have been connected for all objects inside the nib file. Apple states that “When an object receives an
awakeFromNib message, it is guaranteed to have all its outlet and action connections already established.” This means you can now comfortably make some changes to properties that would have otherwise been nil during the init phase. This allows you to put that custom code back into the view subclass, properly encapsulating the functionality.