What is the difference between initWithCoder:, initWithNibName:, and awakeFromNib?

Answer Wiki

 
  • initWithNibName:bundle: is a message sent to a view (or window) controller in order to create the controller; thus, before the nib is loaded. (Possibly long before. It is not part of the nib loading process.)
  • initWithCoder: is a message sent to every object in an archive (including a nib) in order to unarchive it; thus, during the nib loading.
  • awakeFromNib is a message sent to every object in a nib after all of its outlets are hooked up; thus, after the nib is loaded.
Two of these methods are initializers, and the third is a method invoked as part of the nib-loading process.

  • initWithCoder:
    This method is the initializer for all archived objects. As objects stored in nibs are archived objects, this is the initializer used when loading an object from a nib. At the time it's called, the object is being deserialized from the nib, but outlets/actions are not yet hooked up. In the context of UIViewController, it's called when the UIViewController is created from the nib.

    initWithNibName:bundle:
    This method is the designated initializer for UIViewController classes. It's used whenever you're creating a UIViewController in code. This is in direct contrast to initWithCoder:, which requires the UIViewController to be created from the nib. This method sets up UIViewController to be able to load a nib on demand (namely, when it's view property is accessed).

    awakeFromNib
    This method is called on every single object that is unarchived from a nib file, after all outlets/actions have been set up. If initWithCoder: is the beginning of the nib unarchiving process, then awakeFromNib is the end. It signals to the object that all objects have been unarchived and that all of its connections are available. In the context of UIViewController, it signals to the view controller that it's now ready to be used.

    When creating a UIViewController, you have two options. The first is to create it in code. If you go this way, you use initWithNibName:bundle:. The second is to create one by loading a nib. If you go this way, the nib loading process automatically invokes both initWithCoder: and awakeFromNib.

    It's important to note that initWithCoder:/awakeFromNib are not unique to UIViewController, while initWithNibName:bundle: is. If you're implementing a UIView subclass you'll encounter the same situation, except this time you have initWithCoder:/awakeFromNib and initWithFrame:. In general, objects unarchived from a nib use initWithCoder:/awakeFromNib, and objects created in code use their designated initializer.

    A common trick to dealing with this sort of situation is to create a "common init" method that's called from both of the initializers:

    - (void)commonInit {
        _myIvar = @"some value";
        _anotherIvar = 3;
    }

    - (id)initWithCoder:(NSCoder *)aDecoder {
        if ((self = [super initWithCoder:aDecoder])) {
            [self commonInit];
        }
        return self;
    }

    - (id)initWithFrame:(CGRect)frame {
        if ((self = [super initWithFrame:frame])) {
            [self commonInit];
        }
        return self;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章