in iOS ~ read.

Conclusion of objective-C structure

The isa pointer of Instance and Class

  • Firstly, let's have a look at the struct objc_class * of Class, objc_class inherits from objc_object which only have a isa.
//Class is in effect a struct pointer of (objc_class *)
typedef struct objc_class *Class;  
//The struct objc_class
struct objc_class : objc_object {  
    Class superclass;
    cache_t cache;
    class_data_bits_t bits;
    class_rw_t *data() { 
        return bits.data();
    }
    void setData(class_rw_t *newData) {
        bits.setData(newData);
    }
    //many set/get methods...
}
struct objc_object {  
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};
struct class_rw_t {  
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint32_t version;
    const class_ro_t *ro;
    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;
    Class firstSubclass;
    Class nextSiblingClass;
    char *demangledName;
#if SUPPORT_INDEXED_ISA
    uint32_t index;
#endif
//some other methods ...
}
  • In the struct code above, we can see that methods, propertys, protocols and some other values are stored in the class's struct.

  • Here is a picture how a class's superclass pointer point to its superclass. Class Structure

  • Take a look at initialization process of NSObject:

+ (id)alloc {
    return _objc_rootAlloc(self);
}
id _objc_rootAlloc(Class cls)  
{
    return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
static ALWAYS_INLINE id  
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)  
{
//This command is to check (checkNil && !cls)'s result which tell complier the result is more possible to be false;
    if (slowpath(checkNil && !cls)) return nil;
#if __OBJC2__
// hasCustomAWZ() method means class or superclass has default alloc/allocWithZone: implementation, note this is is stored in the metaclass
    if (fastpath(!cls->ISA()->hasCustomAWZ())) {
// FAST_ALLOC means
//   FAST_HAS_CXX_CTOR is set
//   FAST_REQUIRES_RAW_ISA is not set
//   FAST_SHIFTED_SIZE is not zero
// FAST_ALLOC does NOT check FAST_HAS_DEFAULT_AWZ because that bit is stored on the metaclass.
        if (fastpath(cls->canAllocFast())) {
            bool dtor = cls->hasCxxDtor();
            id obj = (id)calloc(1, cls->bits.fastInstanceSize());
            if (slowpath(!obj)) return callBadAllocHandler(cls);
            obj->initInstanceIsa(cls, dtor);
            return obj;
        }
        else {
            // Has ctor or raw isa or something. Use the slower path.
            id obj = class_createInstance(cls, 0);
            if (slowpath(!obj)) return callBadAllocHandler(cls);
            return obj;
        }
    }
#endif
    if (allocWithZone) return [cls allocWithZone:nil];
    return [cls alloc];
}
//The slow Path: class_createInstance
//The fast path: initInstanceIsa, return value type is objc_object;
inline void  
objc_object::initInstanceIsa(Class cls, bool hasCxxDtor)  
{
    assert(!cls->instancesRequireRawIsa());
    assert(hasCxxDtor == cls->hasCxxDtor());
    initIsa(cls, true, hasCxxDtor);
}
//Here is the struct of objc_object
struct objc_object {  
private:  
    isa_t isa;
//other methods
}
  • Here is a image!

Instance' and class' method calling trace

  • There is a classical image: conclusion of instance and class isa trace

  • All in all:

    • Instance's isa point to its Class
    • Class' isa point to its meta-class
    • Meta-class' isa point to its root class' meta-class.
    • Class' superclass pointer point to its superclass' Class. If Class have no superclass, it's superclass point to nil.
    • Meta-class superclass point to its superclass' meta-class.
    • The superclass of root class' meta-class point to root class' Class.
  • Instance call trace
    • Instance can use its isa to find its' Class ßand check if the method is exist int its Class's methodList, and then check the superclass if the method not exist.
  • Class call trace
    • Class can use its isa find meta-class, it will contine find its superclass via superclass pointer if the method doesn't exist.

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2mln51y7cr0go

comments powered by Disqus