Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Objective-C runtime

This is an excerpt from Objective-C runtime programming guide:

When a new object is created, memory for it is allocated, and its instance variables are initialized. First among the object’s variables is a pointer to its class structure. This pointer, called isa, gives the object access to its class and, through the class, to all the classes it inherits from.

isa is declared in NSObject like this:

Class   isa;

In its turn Class is nothing more than a pointer to the struct

typedef struct objc_class *Class;

And now let's look at this structure:

struct objc_class {
Class isa;

#if !__OBJC2__
Class super_class                                        OBJC2_UNAVAILABLE;
const char *name                                         OBJC2_UNAVAILABLE;
long version                                             OBJC2_UNAVAILABLE;
long info                                                OBJC2_UNAVAILABLE;
long instance_size                                       OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

}

We can see that the pointer to the super class (as well as all the rest of the struct's members except another one isa) is unavailable in the latest version of Objective-C.

So my question is how an object can get access to its superclass if super_class pointer is not available? Does it get access to the superclass through this another one isa pointer? But how exactly it happens? How it works? Can anyone explain it?

like image 236
Andrey Chernukha Avatar asked Mar 09 '13 10:03

Andrey Chernukha


People also ask

Does Swift use Objective-C runtime?

Even when written without a single line of Objective-C code, every Swift app executes inside the Objective-C runtime, opening up a world of dynamic dispatch and associated runtime manipulation.

Is Objective-C outdated?

Programming in Objective-C will not become obsolete any time soon because, thanks to its 20 years of existence, it has a large code base, a number of apps maintained, and third-party framework with Objective-C at its core. These solutions and libraries are unlikely to be rebuilt from scratch with a new language.

Is Objective-C deprecated?

It won't be deprecated, but it'll move to Florida to enjoy its golden years. It'll spend days running the legacy app with a million lines of code, and its nights sipping margaritas with the OAuth library everyone fears rewriting.


2 Answers

just checked the source file

objc-class.m

Class class_getSuperclass(Class cls)
{
    return _class_getSuperclass(cls);
}

runtime-new.mm

#define newcls(cls) ((class_t *)cls)

Class 
_class_getSuperclass(Class cls)
{
    return (Class)getSuperclass(newcls(cls));
}

static class_t *
getSuperclass(class_t *cls)
{
    if (!cls) return NULL;
    return cls->superclass;
}

so Class is actually a pointer to class_t

objc-runtime-new.h

typedef struct class_t {
    struct class_t *isa;
    struct class_t *superclass;
    Cache cache;
    IMP *vtable;
    uintptr_t data_NEVER_USE;  // class_rw_t * plus custom rr/alloc flags

    class_rw_t *data() const { 
        return (class_rw_t *)(data_NEVER_USE & ~(uintptr_t)3); 
    }
    void setData(class_rw_t *newData) {
        uintptr_t flags = (uintptr_t)data_NEVER_USE & (uintptr_t)3;
        data_NEVER_USE = (uintptr_t)newData | flags;
    }

    bool hasCustomRR() const {
#if CLASS_FAST_FLAGS_VIA_RW_DATA
        return data_NEVER_USE & (uintptr_t)1;
#else
        return data()->flags & RW_HAS_CUSTOM_RR;
#endif
    }
    void setHasCustomRR(bool inherited = false);

    bool hasCustomAWZ() const {
#if CLASS_FAST_FLAGS_VIA_RW_DATA
        return data_NEVER_USE & (uintptr_t)2;
#else
        return data()->flags & RW_HAS_CUSTOM_AWZ;
#endif
    }
    void setHasCustomAWZ(bool inherited = false);

    bool isRootClass() const {
        return superclass == NULL;
    }
    bool isRootMetaclass() const {
        return isa == this;
    }
} class_t;

and this is the struct that holds everything

anyway, these are internal implementation details and should not be relied on. so do not write code that rely on these because they may broken on next runtime update

like image 154
Bryan Chen Avatar answered Oct 18 '22 19:10

Bryan Chen


dont rely on any internals of the class struct. -- you don't rely on other pals instance variables either! you look for properties

all you can safely do with the runtime is in runtime.h

for getting the superclass e.g.call class_getSuperclass

like image 1
Daij-Djan Avatar answered Oct 18 '22 19:10

Daij-Djan