LuisABOL
LuisABOL

Reputation: 2991

How are instance variables and methods stored in an Objective-C 2.0 object?

In the legacy version of Objective-C, an objc_class struct is implemented like this:

struct objc_class {
    Class isa;
    Class super_class;
    const char *name;
    long version;
    long info;
    long instance_size;
    struct objc_ivar_list *ivars;
    struct objc_method_list **methodLists;
    struct objc_cache *cache;
    struct objc_protocol_list *protocols;
};

So, the struct that represents an object stores a pointer to the object's class, a pointer to the the object's super class, the object's class name, the object's version, info and instance size, the object's instance variables list, the object's methods list, the object's cache and the object's protocols list. The presence of these fields in the struct that represents an object is pretty understandable since each one of them stores an information about the object.

However, the Objective-C 2.0 implementation of the same struct objc_class is like this:

struct objc_class {
    Class isa;
};

So, in this version of objc_class, there is only one field in the struct: a pointer to the object's class struct.

My question, then, is how are the other information about the object stored in Objective-C 2.0 since there is only one field in the struct that represents the objects?

Upvotes: 5

Views: 375

Answers (1)

Richard J. Ross III
Richard J. Ross III

Reputation: 55533

It's all in the new (ok, well not so new anymore) non-fragile ABI.

Basically, instead of storing iVars inside of a struct like you used to (which would break inheritance if a superclass changed it's iVar layout), the compiler puts iVar redirection through another layer, similar to objc_setAssociatedObject at runtime.

This allows for a few interesting scenarios. Consider the following:

@interface A { // part of libA.a
   id var1;
   int var2;
   float var3;
} 

@end

@interface B : A { // part of libB.a
   id var4;
}

@end

Now, what if some time down the road, we need to change class A, and we determine we need more precision in var3 (converting it to a long double, for example)?

In the older, fragile ABI, we would be screwed until the maker of libB updated. However, with this new, non-fragile ABI, we have the flexibilty to change all of this while libB still works.

While in theory this may be slower by a few cycles, it adds easier ways to lookup iVars at runtime, more flexible subclassing, and support for different kinds of iVars (__weak, for example).

Upvotes: 7

Related Questions