preface

The previous article had a better understanding of OC objects. OC objects understand portals. At the end of the analysis of isa pointer structure of OC object (part 2), I verified through pointer printing that isa pointer of class object points to class, ISA pointer of class points to metaclass, ISA pointer of metaclass points to root metaclass, ias pointer of root metaclass points to itself. Let’s review it

The pointer to isa

We create two classes: Person inherits from NSObject and Man inherits from Person

@interface Person : NSObject
@end

@interface Man : Person
@end
Copy the code

Run print:The figure above shows Preson’s ISA direction. Let’s take a look at Man’s ISA direction

The isa pointer has nothing to do with the parent class

Now let’s look at inheritanceYou can see that the parent of Man is Person, and the parent of Person is NSObject. The relationship between inheritance and isa Pointers can be illustrated in the following figure

Let’s remember a few key points from the diagram. (Object methods and attributes are stored in classes. Metaclasses are where class methods are stored.)

  • 1. Objects do not have inheritance relationships, which only exist on class objects and metaclass objects
  • 2. Isa Pointers do not point to superclasses
  • 3. The isa pointer to the root metaclass (NSObject) points to itself, but inherits from NSObject.

The above is known by printing the address information

Class uniqueness

As we can see from the print above, the address of the printed NSObject is 0x000000001003340F0, and the address of the root metaclass NSObject is the same for both Person and man, indicating that the root metaclass NSObject is unique in memory.

Let’s see if the class is unique and write the following code

Class class1 = [Person class];
Class class2 = [Person alloc].class;
Class class3 = object_getClass([Person alloc]);
NSLog(@"%p->%p->%p", class1, class2, class3);
Copy the code

Let’s look at the print:

We find that the printed addresses are all the same, which means that the class object is also unique in memory, only one copy.

Above is the uniqueness phenomenon found by printing the address, now we continue to explore the structure of the class, we come through the source analysis

Class structure analysis

The source code we use here is objC4-781

The structure of the class

Superclass = man.superclass; superclass = man.superclassClick Class again to see the following methodWith these two methods in mind we click on objc_class to find the following codeObjc_class is derived from objc_Object. What is inside objc_Object?The method is too long to cut the first part, we found that the bread is goodisa. This isAll object creation will have isaAnd there will beSuperclass, cache, bitsAnd other information. So what’s in all this information?

Class structure internal analysis

To explore the class_data_bits_t bits

Cache_t is a cache, and it contains the contents of the cache. Click thereI don’t know what they are, but let’s look at class_data_bits_t, okayIt’s hard to understand what’s inside, so how can we explore its internal structure?

Memory migration

In the main function, write the following code:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int a = 10;
        int b = 10;
        NSLog(@"%d---%p", a, &a);
        NSLog(@"%d===%p", b, &b);
        Person *person = [Person alloc];
        Person *person1 = [Person alloc];
        NSLog(@"%@--->%p", person, &person);
        NSLog(@"%@===>%p", person1, &person1);
    }
    return 0;
}
Copy the code

The printed result is as follows:The following results are printed because:

From the figure above, we can know that a and b are copies of values of 10, and a and b are variables

Person outputs the address of the person object, and person outputs the memory address that holds the address

Let’s go ahead and write the following code

Int c [4] = {1, 2, 3, 4}; int *d = c; NSLog(@"%p->%p->%p", &c, &c[0], &c[1]); NSLog(@"%p=>%p=>%p", d, d+1, d+2);Copy the code

Print the following:

We find that the starting position of C is the same as the first element of C, and the position of D is the same as the first element of C, and d+1 is the same as the second element of C. From the above we can see that we can remove values directly by position offset.

To verify this, write the following code

for (int i = 0; i < 4; i++) {
    int value = *(d+i);
    NSLog(@"-->%d", value);
}
Copy the code

Print the result

Note The value can be specified by memory offset.*(d+ I) means to fetch the value under the d+ I address

Explore the memory offset of class_data_bits_t bits

We know that if we know the memory offset of this property in the structure, we can get the memory address of the structure and print out its internal information

To know the offset position of class_datA_bits_t bits, we must know the size of the cache before: Class ISA (inherited from objc_object), Class superclass, and cache_t.

Class ISA and Class superclass are Pointers, so they are both 8 bytesLet’s take a look at the size of cache_t cache(cache_t Its size is determined by its internal properties) Above is an internal implementation of the cache_t method. We see a lot of attributes, but keep in mindStatic does not take up space in this class; it is a global variable, so you only need to find no static attribute. To sum up, cache_t occupies 16 bytes. Plus 8 bytes of isa before, 8 bytes of Superclass, soThe memory offset of class_DATA_bits_t bits in the structure is 32 bytes.

Explore the internal structure of class_datA_bits_t bits by memory offset

We write the following code in Person.h:

@interface Person : NSObject
@property (nonatomic, copy)NSString *name;
@property (nonatomic, copy)NSString *address;
@property (nonatomic, assign) NSInteger age;
- (void)likeFood;
- (NSString *)sleepTime;
+ (void)likeColor;
+ (NSString *)workTime;
@end
Copy the code

Create the Person object interrupt point and print itWe printed the properties

It calls the method interpretation, and it does the same for the object method

We just got the properties, now let’s go get the methods

In the above method we found the [person.cxx_destruct] method, which was originally intended for C++ object destruct, and ARC borrowed this method to insert code for automatic memory freeing.

We find that there are no class methods because what we explored above isClass class_data_bits_t.The class_datA_bits_t class stores the attributes of the object and the object methods, which are stored in the metaclass. We need to find class_datA_bits_t of the metaclass to find the class method

Inquiry class method

The Person metaclass is a class object whose ias pointer points to a metaclass.Procedures and object methods are consistent, so what’s the point here

The last

Classes containing isa Pointers, superclass, cache_t, class_datA_bits_t, superclass, class_datA_bits_t, We mainly introduced class_datA_bits_t, which contains class_rw_t. Class_rw_t contains methods(), properties(), and protocols(), which store object methods, properties, and proxy protocols respectively. This part of the puzzle is that the isa of the object points to the class, the class points to the metaclass, and the metaclass points to the root metaclass. Print address, ISA pointer address, the first address of the object, clear typing more understanding. This is to open up the inside of the class and see what’s inside in preparation for the runTime.