6

What is the difference between declaring an ivar within an @interface versus putting a variable within an @implementation in a .m file?

@interface MyClass : NSObject {
  int num;
}
- (void)doSomething;
@end

vs.

@implementation MyClass   
int num2;

- (void)doSomething {
  num = 137;
  num2 = 138;
}
@end

Is there ever a time when you want to put a variable within the @implementation?

jscs
  • 63,694
  • 13
  • 151
  • 195
nickfox
  • 2,835
  • 1
  • 26
  • 31

3 Answers3

8

The difference between using an ivar and declaring a variable inside the implementation is that the variable within the implementation is at file scope and global. That means all instances (and any static methods) will share the same variable; i.e. if one instance of your object changes the variable, it will change it for all instances.

The use case for defining it at file scope is to store things for static methods (methods that act directly on the class instead of an instance of the class). A really common use case for this is the Singleton design pattern. You can define a static instance of your class within this file so that at any time, you can ensure you are accessing the same instance. You can provide a static method that returns this instance so any object in your code can access that same object by calling the method directly on your class.

Update 4/17/14

Common practice now is to use Properties. This creates getters and setters for you automatically making the class more extensible (if you decide to change the way a property works, perhaps you want to change it to always be calculated on the fly, the public interface of the class does not need to change).

You can use private class extensions to declare "private" properties and methods. This has the effect of protecting certain properties and methods from being accessed by outside classes.

drewag
  • 93,393
  • 28
  • 139
  • 128
  • A very good explanation could be this: [Class variable defined at @implementation rather than @interface?](http://stackoverflow.com/a/2571565/818506) – rohan-patel Mar 29 '13 at 15:23
  • This answer is a little dated. It is now much better to put the ivars in the `@implementation` but be sure to use curly braces. If in curly braces, the variables will be instance variables. Without the braces, the variables will be global variables. – rmaddy Apr 17 '14 at 04:02
  • "much better" is an exaggeration. I would say that you want to put it into the implementation file whenever it is a variable that other classes should not be messing with. However, it is usually preferable to use properties now. You can use [private class extensions to declare "private" properties and methods](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html#//apple_ref/doc/uid/TP40011210-CH6-SW6). – drewag Apr 17 '14 at 16:22
  • but thank you for pointing out that the answer is somewhat outdated. I provided an update to modernize it. – drewag Apr 17 '14 at 16:28
4

As far as I know, putting a variable declaration inside the @implementation is no different from putting it outside the implementation: It's not an ivar, it's just a variable declared at file scope.

One use is for declaring the equivalent of C++ static members. For example:

@implementation MyClass

static int s_count = 0;

- (id)init {
  if ((self = [super init]))
    ++s_count;
  return self;
}

- (void)dealloc {
  --s_count;
  [super dealloc];
}

Assuming init is your only initializer, then s_count will contain the total number of instances of MyClass that are active.

Tony
  • 3,470
  • 1
  • 18
  • 23
  • 2
    I.e., static global variables can be used as class variables. –  Apr 06 '11 at 01:05
  • 2
    I was just talking to some people about it and they where saying the ivar is an instance variable while the variable declared within the @implementation is "global, as in not per-instance." To me that sound like static. I get what the ivar is, but still unclear about the variable within an @implementation and when it should be used. – nickfox Apr 06 '11 at 01:07
  • 5
    @nickfox _Global variables_, static or not, have the same lifetime as the program and can be used by any method or function in the implementation file, which is why they can be used as class variables. A _non-static global variable_ can also be used by other implementation files, similar to a public class variable. A _static global variable_ can only be used by the implementation file that declares it, hence acting as a private class variable. –  Apr 06 '11 at 01:15
1

Note: Historically, the interface required declarations of a class’s instance variables, the data structures that are part of each instance of the class. These were declared in braces after the @interface declaration and before method declarations:

Instance variables represent an implementation detail, and should typically not be accessed outside of the class itself. Moreover, you can declare them in the implementation block or synthesize them using declared properties. Typically you should not, therefore, declare instance variables in the public interface and so you should omit the braces.

(source)

j0k
  • 22,600
  • 28
  • 79
  • 90