Difference between variable declaration in @Implementation and @Interface in .m file

I have been studying Objective-C for some time. From what I learned, I know that when you declare a variable inside @interface in a .h file, access to this variable can be publicly published (similar to a public variable in java).

 @interface MyObject @property NSInteger intData; @end 

But when you declare it inside @interface in the .m file. Access to it can only be obtained in the .m file, only in @implementation, unless you provide it with a getter and setter.

 @interface MyObject () @property NSInteger intData; @end 

But I also noticed another way of declaring a variable declaring it under @implementation

 @implementation NSInteger intData; @end 

and I see that it works the same as the declaration in @interface with @property in the .m file

I do not understand the difference between the two (declaring in @implementation and under @interface (in .m file ).

I already looked at the stack about this, but they all talked about the difference between @implementation and @interface (in the .h file ). Therefore, think that this is not a duplicate.

+6
source share
2 answers

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 ; // you are not allowed to access it by this variable } - (NSInteger) i ; - (void) setI:(NSInteger)value ; @end 

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 ; // Causes the property to line up with the ivar by the same name. @end 

Same as:

 @interface MyClass : NSObject { NSInteger i ; // you ARE allowed to use this since you defined it } - (NSInteger) i ; - (void) setI:(NSInteger)value ; @end 

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 ; // only makes a getter method 

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.)

+4
source

When you declare a property in @interface MyObject (){} , you declare it in what is called an anonymous or class category. Since it is declared in the .m file, it appears only inside this file (other classes do not see it). However, you could just as well declare this category in your .h file, in which case it will be visible to other classes.

The NSInteger intData inside the @implementation part of your class does not actually declare the instance variable. It declares a global variable, which means that there is one instance of this file that is used by your entire application, or, if you want to look at it this way, all instances of your class (since it is the only one who knows this global variable).

+4
source

All Articles