title: Initializing instance variables in iPhone Development / Objective-C
body: <p>Being fairly new to iPhone / Objective-C development, I wanted to ask this question to make sure that I'm going about initializing instance variables correctly in different scenarios. So below, I'm going to present a few scenarios and if anyone sees anything being done incorrectly, can they please let me know. (Note: For my examples I'll be using "instanceVariable" for the instance variable we're looking to initialize, which is an object of class "InstanceVariableClass".)</p>
  
  <p><strong>Scenario 1: Initializing in a Non UIViewController Class</strong></p>
  
  <p><em>a) New Allocation</em></p>
  
  <pre><code>- (id)initWithFrame:(CGRect)frame {
  
      self = [super initWithFrame:frame];
      if (self) {
          instanceVariable = [[InstanceVariableClass alloc] init];
      }
      return self;
  }
  </code></pre>
  
  <p>In the initializer, it's OK to access the variable directly (ie not through it's property) and allocate it. When you call alloc, the newly created object will be automatically retained, which will work perfectly later on when you use it with your getter and setter methods. You don't want to allocate the variable using a property, i.e. <code>self.instanceVariable = [[InstanceVariableClass alloc] init];</code> or else you'll be retaining it twice (once in your setter method, and one with the alloc).</p>
  
  <p><em>b) Parameter</em></p>
  
  <pre><code>- (id)initWithFrame:(CGRect)frame object(InstanceVariableClass*) theInstanceVariable {
  
      self = [super initWithFrame:frame];
      if (self) {
          instanceVariable = [theInstanceVariable retain];
      }
      return self;
  }
  </code></pre>
  
  <p>Once again, OK to directly access your instance variable in the initializer. Since you're not allocating the variable and simply are wanting to own a copy that was passed into you, you need to have it explicitly retain itself. If you had used your setter method, it would've retained it for you, but want to avoid accessing properties in the initializer. </p>
  
  <p><em>c) Convenience Method</em></p>
  
  <pre><code>- (id)initWithFrame:(CGRect)frame {
  
      self = [super initWithFrame:frame];
      if (self) {
          instanceVariable = [[InstanceVariableClass returnInitializedObject] retain];
      }
      return self;
  }
  </code></pre>
  
  <p>When using a convenience method to return a new object, you also need to explicitly retain for the same reasons as a parameter. The convenience method (if implemented properly) will have autoreleased the new object it generates, so we don't have to worry about doubly retaining it.  </p>
  
  <p><strong>Scenario 2: Initializing in a UIViewController Class</strong></p>
  
  <p><em>a) New Allocation</em></p>
  
  <pre><code>- (void) viewDidLoad // or - (void) loadView if you implemented your view programmatically
  {
      [super viewDidLoad];
  
      InstanceVariableClass *tempInstanceVariable = [[InstanceVariableClass alloc] init];
      [self setInstanceVariable: tempInstanceVariable];
      [tempInstanceVariable release];
  }
  </code></pre>
  
  <p>In a UIViewController, you want to do your instance variable initializing in the viewDidLoad method to employ the practice of lazy loading, or loading in your variables only at the exact moment you need them. Outside of the initializer, it's bad practice to access the variable directly, so we'll now use our synthesized setter method to set the variable. You don't want to allocate the variable using the setter method, ie <code>[self setInstanceVariable] = [[InstanceVariableClass alloc] init];</code> or else you'll be retaining it twice (once in your setter method, and one with the alloc). So the best practice is to create a new temp variable, initialize the temp variable, set your instance variable to the temp variable, then release the temp variable. The synthesize setter method will have retained the variable for you. </p>
  
  <p><em>b) Convenience Method</em></p>
  
  <pre><code>- (void) viewDidLoad // or - (void) loadView if you implemented your view programmatically
  {
      [super viewDidLoad];
  
      [self setInstanceVariable: [InstanceVariableClass instanceVariableClassWithInt:1]];
  }
  </code></pre>
  
  <p>Initializing an instance variable outside of an initializer method, we can simply use our setter method to set and retain the object that is generated. The convenience method (if implemented properly) will have autoreleased the object it returns, so we don't have to worry about doubly retaining it.  </p>
  
  <p>That's what I have so far. If anyone can find any flaws in my reasoning, or think of any other scenarios I forgot to include, please let me know. Thanks.</p>