Question: Where does an object’s ISA pointer point to?

A. Isa pointer

The ISA pointer to instance points to class. When an object method is called, the class is found through the ISA pointer to instance, and finally the implementation of the object method is found.

The ISA pointer to class points to meta-class. When a class method is called, the meta-class is found through the ISA pointer to the class, and finally the implementation of the class method is found to call.


Ii. The class of the superclass

2.1 Superclass pointer to a class object

When a Student instance calls a Person object method, it finds Student’s class through ISA, then finds Person’s class through superClass, and finally finds the implementation of the object method.

2.2 Superclass pointer to a meta-class object

When a Student class calls a Person class method, the isa pointer is used to find Student’s meta-class, then the superclass is used to find Person’s meta-class, and finally the implementation of the class method is found


3. Isa details

Starting with 64bit, ISA needs to perform a bit operation to calculate the real address

Information about ISA_MASK can be found in the source code


Isa, superclass summary

  • The ISA of an instance refers to class
  • The ISA of a class object points to meta-class
  • The ISA of a meta-class points to the meta-class of the base class
  • The superclass of a class object refers to the class of its superclass
    • If there is no superclass, the superclass pointer is nil
  • The superclass of a meta-class refers to the meta-class of the superclass
    • The superclass of the meta-class of the base class points to the class of the base class
  • Instance calls the path of an object method
    • Superclass = superclass; superclass = superclass
  • Class calls the trace of a class method
    • Isa finds meta-class, method doesn’t exist, finds superclass

4. Class and meta-class structures

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

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

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */
Copy the code

In the runtime.h header we can see that a conditional compilation will not be executed if it is not in objC2, so in OC2.0 this code is obsolete. The struct objc_class structure is no longer available in OC2.0, as can be seen from OBJC2_UNAVAILABLE.

4.1 Viewing struct objc_class structure

Struct objc_class struct runtimenew.h (objc-runtimenew.h); Struct objc_class struct objc_class

struct objc_class : objc_object {
    Class isa;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable- method cache
    class_data_bits_t bits;    // class_rw_t * plus custom RR /alloc flags- Used to get specific class information. . . }Copy the code

Note: the colon syntax stands for inheritance, and the objc_class structure inherits from objc_object, which is the syntax of C++.

class_rw_t *data() const {
    return bits.data();
}
Copy the code
class_rw_t* data() const {
    return (class_rw_t *)(bits & FAST_DATA_MASK);
}
Copy the code

The following figure shows the code structure of the old version. You can refer to the source code of the new version

The struct objc_class structure contains the above code and returns class_rw_t, which is a readable and writable form.

In the class_rw_t header we can see a piece of public code that returns type class_rw_ext_t. As shown in the figure below

class_rw_ext_t *ext() const {
    return get_ro_or_rwe().dyn_cast<class_rw_ext_t *>();
}
Copy the code

Entering the class_rw_ext_t header file, we can see the definitions for the method list, attribute list, and protocol list. As shown in the figure below

struct class_rw_ext_t {
    const class_ro_t *ro;
    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;
    char *demangledName;
    uint32_t version;
};
Copy the code

In the class_rw_ext_t structure, we can see the definitions of instanceSize and ivars in the class_ro_T header file. The following figure shows some of the code in the header file.

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    const uint8_t * ivarLayout;
    
    const char * name;
    method_list_t * baseMethodList;
    protocol_list_t * baseProtocols;
    constivar_list_t * ivars; . . .Copy the code

Summary: Where is the OC class information stored?

  • Object methods, properties, member variables, and protocol information are stored in class objects.
  • Class method, stored in a meta-class object.
  • The specific value of the member variable, stored in the instance object.