First, you do not declare a variable; you declare a property. The property is supported by the instance variable, but it also adds methods. Here is an explanation of the variable locations:
@interface MyClass : NSObject { NSInteger i ; } @end
This is the place to place the instance variable in your class. It is only available using the methods of your class and categories. (Sidenote: it may be accessible from the outside, but this is not recommended)
Another example:
@interface MyClass : NSObject @end @implementation MyClass { NSInteger i ; } @end
It is also an instance variable, but is only accessible using methods written inside this block. (Sidenote: it can be accessed by digging up a class definition, but this is not a recommended (or normal) practice)
Another example:
@interface MyClass : NSObject @property NSInteger i ; @end
Same as:
@interface MyClass : NSObject { NSInteger _i ;
This is a property that people can get and set. You use this variable in your methods or in other methods like:
NSLog ( @"The value is %i" , self.i ) ; // if it your instance method NSLog ( @"The value is %i" , object.i ) ; // if it object instance method
Another example:
@interface MyClass : NSObject { NSInteger i ; } @property NSInteger i ; @end @implementation MyClass @synthesize i ;
Same as:
@interface MyClass : NSObject { NSInteger i ;
Here you can use the getter / setter methods or the instance variables themselves. However, you should usually use methods because you have [implicitly] declared them atomic so that they synchronize the threads. If you want it to NOT execute threads (and speed it up until you intend to use it in a multi-threaded environment):
@property (nonatomic) NSInteger i ; @property (nonatomic,readonly) NSInteger i ;
I would recommend avoiding this for a while and using direct properties, because it will help to avoid many common mistakes. If you do not profile your program and determine that this is causing performance loss, you should probably just use properties.
Another example:
@interface MyClass : NSObject @end @implementation MyClass NSInteger i ; @end
This is NOT an instance variable. This is a global variable, which, as it turned out, was written inside the @implementation .
See above how to turn this into an instance variable (i.e. put it in curly braces).
One more note:
Declaring a property like this:
@interface MyClass () @property NSInteger i ; @end
Does not make it closed. However, it is hidden in a file that is usually inaccessible to people, so the compiler does not know that the property exists.
Other functions elsewhere in your CAN code may still call:
[yourObject i]
To get the value of this property, but first you need to know it.
Adding the answer to the question in the comments:
The default properties are atomic. It does not necessarily follow the strict definition of an atom (it may be a worm that I suggest you donβt look right now), but it has the same effect: the threads are guaranteed to see the full and current value, regardless of when another stream writes to it. This usually happens when synthesizing getter / setter methods:
- (NSInteger) i { @synchronized(self) { return i ; } } - (void) setI:(NSInteger)value { @synchronized(self) { i = value ; } }
If you specify nonatomic , this will synthesize them:
- (NSInteger) i { return i ; } - (void) setI:(NSInteger)value { i = value ; }
If your property is atomic , then you should never access ivar directly. This violates the thread protection you gave for a start. (Sidenote: There are times when you can, but wait until you get to know the threads / sync before trying to do it.)