Designated Initializer?

Discussion in 'iOS Programming' started by Darkroom, Jun 23, 2009.

  1. Darkroom Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #1
    in my nib, i have a view called "fader". in the nib, it's set with a background color of red. however, when i start the app, i want "fader" to have a yellow background

    Code:
    [COLOR="Green"]// The designated initializer.
    //Override to perform setup that is required before the view is loaded.[/COLOR]
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    	{
    	if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
    		{
    		fader.backgroundColor = [UIColor yellowColor];
    		}
    	return self;
    	}
    
    it is my understanding, that this method is the initializer of the nib file. so if i want to change the background color before the nib shows up on screen, this is the place to do it. but it doesn't work

    Code:
    - (void)viewDidLoad
    	{
    	fader.backgroundColor = [UIColor yellowColor];
    	[super viewDidLoad];
    	}
    
    this works.

    Confusing! since viewDidLoad works to set my objects in certain ways (after the nib is loaded), i don't understand what "The designated initializer" is used for... does not setting a background color fit into "setup that is required before the view is loaded."?
     
  2. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #2
    The nib isn't loaded until the view property is accessed. In the normal sequence of events this happens after you push the view controller, or inside the pushViewController method. Your initWithNibName method has already returned at that point. Inside initWithNibName IBOutlets haven't been set yet.

    The designated initializer concept isn't related to this. The designated initializer is an init method that's called by other init methods. When your outlets are set is related to the view accessor and when the nib is really loaded.

    Also, be aware that your view can be loaded multiple times in response to memory warnings.
     
  3. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #3
    sorry, i'm not following clearly except that what is inside this initializer method is actually not executed code before the Nib is loaded, but while the nib is loading (?)... so objects within the nib are not accessible in this method... is that right?

    Code:
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    	{
    	if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
    		{
    		NSLog(@"hi");
    		}
    	return self;
    	}
    
    nothing in the console...

    so if an NSLog doesn't execute here, i have no idea what can/does. which method is intended for initializer code like userdefaults, etc?
     
  4. Luke Redpath macrumors 6502a

    Joined:
    Nov 9, 2007
    Location:
    Colchester, UK
    #4
    If you're manually loading your controller in code (using initWithNibName) then that will be the one to override; however if you have set the nib name for the controller inside another nib (your main nib?) then it will be loaded using initWithCoder.
     
  5. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #5
    yes, my view controller xib is inside MainWindow.xib. so i built the TestAppViewController.xib with a bunch of objects and a UIView that i placed over all the objects, covering them from view. this view, which is black, will be set to hidden in IB so i will still be able to see there are other objects present. when i start my app, i want this black colored view to be set unhidden.

    Code:
    @interface TestApp : UIViewController
    	{
    	IBOutlet UIView *blackView;
    	}
    
    @property (nonatomic, retain) UIView * blackView;
    @end
    
    -==-=-=-=-=-=-
    
    #import "TestAppViewController.h"
    
    @implementation TestApp
    
    @synthesize blackView;
    
    
    - (id)initWithCoder:(NSCoder *)coder
    	{
    	if (self = [super initWithCoder:coder])
    		{
    		self.blackView.hidden = NO;
    		}
    	return self;
    	}
    
    - (void)viewDidLoad
    	{
    	//Fade In Animation Block
    	[UIView beginAnimations:nil context:NULL];
    	[self.blackView setAlpha:0.0];
    	[UIView commitAnimations];
    	[super viewDidLoad];
    	}
    
    @end
    
    so, as you can see, i want the initialization of the black view to become unhidden, so that it can fade out in the viewDidLoad method. but it's just not getting called.

    is this happening because the initWithCoder is setting the blackView to unhide, but then after the initialization is finished loading, it's now time for the xib to load. when the xib is loaded, the blackView is hardset to hide... so is this initialization actually working, but i'm not seeing it because the view is hard coded to hide in the xib, which is executed after the initialization code?
     
  6. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #6
    What is the value of blackView in initWithCoder?
     
  7. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #7
    are you telling me that initialization methods only take values? i set up a BOOL in initWithCoder to mark the xib...

    Code:
    -(void)initWithCoder:(NSCoder *)coder
    {
    if (self = [super initWithCoder:coder])
         bool = yes
    }
    
    -(void)viewDidLoad
    {
    if (bool)
         //show this object
    }
    
    so initWithCoder (and assuming initWithFrame, etc.) only assigns values and can not hide objects?
     
  8. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #8
    You're not understanding the sequence of events. The init methods are the first methods that are called for any object. When the init methods are called their outlets have not yet been set. The first place that your code can access the outlets is viewDidLoad (or maybe loadView but I'm not sure about that).

    In your first post above you explain that you can access the outlets in viewDidLoad. That's good. That's what's supposed to happen. You also mentioned that you can't access the outlets. That's also good. That's what's supposed to happen.

    Yes, you can access other kinds of instance variables from the init methods, like BOOLs or NSStrings or others.
     
  9. Darkroom thread starter Guest

    Darkroom

    Joined:
    Dec 15, 2006
    Location:
    Montréal, Canada
    #9
    thanks. i'm getting it. i was just a bit mislead by apple's built in comment

    Code:
    // The designated initializer.  Override to perform setup that is required before the view is loaded.
    
    i read it like

    Code:
    // The designated initializer.  Override to perform setup [COLOR="Red"][I](of the view)[/I][/COLOR] that is required before the view is loaded.
    
     
  10. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #10
    OK. The term designated initializer has a very specific meaning that is explained in the Obj-C 2.0 Guide. You should read that.
     

Share This Page