Tutorial :Why are instance variables defined in the header file in Objective-C



Question:

I can understand defining the functions in the @interface of the header file, but why the instance variables? Shouldn't the instance variables be private, only accessible through messages?


Solution:1

The reason is so it can calculate offsets of variables for subclasses.

@interface Bird : NSObject {      int wingspan;  }  @end  @interface Penguin : Bird {      NSPoint nestLocation;      Penguin *mate;  }  @end  

Without knowing the structure of the "Bird" class, the "Penguin" class can't calculate the offset of its fields from the beginning of the structure. The penguin structure looks kind of like this:

struct Penguin {      int refcount; // from NSObject      int wingspan; // from Bird      NSPoint nestLocation; // from Penguin      Penguin *mate; // from Penguin  }  

This has a side effect: if you change the size of a class in a library, you break all the subclasses in apps that link to that library. The new properties work around this problem.


Solution:2

Although they are declared in the header file, all instance variable in Objective-C have @protected access by default. This means the variable is accessible within the class that declares it and any class inheriting from that class.

Here is Apple's documentation on defining an Objective-C class: Defining Classes

Notice the section titled "The Scope of Instance Variables".


Solution:3

I think it is a technical issue. If I understand correctly, a Objective-C class is just a fancy C struct. And for a struct to be used its size must be known. (Like how would sizeof() work otherwise)


Solution:4

In case anyone stumbles across this question -- as of XCode 4.2 with the LLVM compiler, you can declare instance variables in the @implementation using the following brace notation:

  @interface SomeClass : NSObject  @end    @implementation SomeClass {    NSString *myInstanceVariable_;  }    - (void)moreMethods {}  @end  

Instance variables generally shouldn't be part of your classes declared public interface -- they're implementation details.

However, MAKE SURE you define your instance variables within the braces or else you'll be defining a global variable that has no relation to the object instance:

  @implementation SomeClass    NSString *whoopsGlobalVariable_;    - (void)moreMethods {}    @end  


Solution:5

Taken from the section of Apple's documentation on defining Objective-C classes, The Role of the Interface:

Although instance variables are most naturally viewed as a matter of the implementation of a class rather than its interface, they must nevertheless be declared in the interface file. This is because the compiler must be aware of the structure of an object where it’s used, not just where it’s defined.


Solution:6

Note that under the Objective C 2.0 new "Modern Runtime" (availabe in iPhone applications and 64-bit Mac OS X 10.5 applications) you do not need to specify the ivars, you can specify the properties and then use @synthesize to generate the ivars.

This is because in the Modern Runtime, ivars have a global indirection symbol that holds the offset for the ivar. This also resolves the fragile base class issue, allowing ivars to be reordered and added without requiring recompiling of subclasses (deleting or renaming ivars may still cause link errors).

However you still have to list properties in the main interface, so there does not seem to be any way to entirely hide private ivars which is unfortunate. You cannot, for example, use a property and @synthesize in a category.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »