Why must I define variables twice in the header file? What differences are there between these variables?
The first definition is here:
@interface MyCont
In modern runtime you do NOT need to declare them twice. Just use:
In you .h
@property (nonatomic) NSInteger selectedIndex;
The part between the {} is the declaration of the iVar. And with your @property you declare getter and setters. In modern runtime if you just use the code above you say basicly the same (your iVar is now _selectedIndex).
As others have pointed out, it is no longer necessary to declare a backing instance variable for a synthesized property in the header.
To make this a bit clearer though: What you're seeing are not two declarations of the same variable, it is one declaration of the variable and one declaration of the property.
A property is basically a set of methods (in this case selectedIndex
and setSelectedIndex:
) that are typically used to access instance variables. There is a difference between a property and an instance variable. The property's setter/getter could do more than just set the variable, in your example, it could also e.g. update the UI to reflect the change of the selected index or the getter could infer the index from some other variable (in this case, there might be a selection index path), etc.
Synthesizing a property simply frees you of implementing those methods yourself and provides you with default implementations that simply set the variable, but you could also implement selectedIndex
and setSelectedIndex:
yourself just like any other method in which case you might either need the instance variable itself or omit it altogether (in case of an inferred property).
What you're seeing was required in earlier versions of Objective-C, but isn't any more.
In the first versions of Objective-C used by NeXT up until the new runtime was introduced (with Objective-C 2.0 on Mac OS X), all instance variables had to be declared as part of the class's structure in its
@interface
. The reason was that if you subclassed a class, the compiler needed to know the instance variable layout of the class so it could see at what offset to put the subclass's instance variables.When properties were introduced, synthesized properties had to be "backed" by an instance variable in the class's structure. Therefore you had to declare both an instance variable and the property.
All of the above is no longer true. Newer Objective-C is less fragile in the way it looks up instance variable offsets, which has meant a few changes:
- not all instance variables need to be in the
@interface
. They can now be defined in the@implementation
: though not in categories due to the possibilities of clashing and other issues.- instance variables for synthesized properties can be inferred and created based on the property definition.
- you can programmatically add instance variables to classes you're creating at runtime (only before you've registered the class as available to the system).
So, to reiterate, you only needed to declare both the instance variable and a synthesized property in older versions of the Objective-C language. What you're seeing is redundant and should not be considered a "best practice".
[Source]