iphoneobjective-ccocoa-touchawakefromnibinitwithcoder

Setting Finished TabBar images when using storyboards?


I am working on an application where the bulk of the UI is setup via a Storyboard in Xcode. One thing that I want to do is specify "Finished" images for the UITabBarItems on a TabBar rather than the default "Stencilled" images that you can access via Interface Builder.

My question is where is the best place to do this, I am currently doing it in awakeFromNib as it needs to be done when things are unarchived from the storyboard, but I as unsure if I should be using initWithCoder: instead, which is best does it matter?

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if(self) {
        UIImage *tabIn  = [UIImage imageNamed:@"TAB_IN"];
        UIImage *tabOut = [UIImage imageNamed:@"TAB_OUT"];

        UITabBarItem *tabBarItem = [self tabBarItem];
        [tabBarItem setFinishedSelectedImage:tabOut withFinishedUnselectedImage:tabIn];
        [tabBarItem setTitle:@"TWO"];
    }
    return self;
}

OR

- (void)awakeFromNib {
    [super awakeFromNib];
    UIImage *tabIn  = [UIImage imageNamed:@"TAB_IN"];
    UIImage *tabOut = [UIImage imageNamed:@"TAB_OUT"];

    UITabBarItem *tabBarItem = [self tabBarItem];
    [tabBarItem setFinishedSelectedImage:tabOut withFinishedUnselectedImage:tabIn];
    [tabBarItem setTitle:@"TWO"];
}

I understand that initWithCoder: is called at the start of unarchiving objects from nibs (contained in the storyboard) when outlets and actions are not yet hooked up. I also understand that awakeFromNib is called at the end of the unarchiving process and signals that the viewController is now ready for use. My feeling is that it really just depends on what you want to do, although using awakeFromNib might prove less problematic as your not going to hit issues where outlets and actions are not yet hooked up.

EDIT:

Let me rephrase this, what situations would you use initWithCoder: as apposed to awakeFromNib and vice versa?


Solution

  • It seems that you've already answered your own question in the paragraph before edit.

    The documentation states that

    When an object receives an awakeFromNib message, it is guaranteed to have all its outlet instance variables set.

    So if you have to access IBOutlet ivars in your initialisation code, you have to do it in the awakeFromNib method.

    Although I prefer initWithCoder: in cases when I do not need to access outlets because it is the proper initialiser method for objects being decoded with NSCoding protocol according to NSCoding documentation:

    initWithCoder: instructs the object to initialize itself from data in the coder provided; as such, it replaces any other initialization method and is sent only once per object

    As a side note though, it does not make much of a difference and in cases when I have to access outlets in my initialization code, I do not implement both awakeFromNib and initWithCoder: for the sake of simplicity. So if outlets are involved I usually implement awakeFromNib and do all the initialisation there.