The nature and classification of OC objects

Oc is an object-oriented language, the underlying implementation is actually C \ C ++ code, so OC object-oriented is based on C \ C ++ data structure, OC objects, classes are mainly based on C \ C ++ in the structure to achieve

1. The nature of OC objects

Object-c is implemented through C/C++, so objects in OC will also be converted to a data structure in C/C++

1. How to convert OC code to C ++ code?

Go to the directory to be converted and run the following command

% clang-rewrite main.m -o main.cppCopy the code

Different platforms support different code platforms: Windows, MAC, iOS; Architecture: Emulator (I386),32bit(ARMV7),64bit(ARM64)

OC object essential % xcrun-sdk iphoneOS clang-arch arm64-rewrite-objc main.m -o main-arm64.cppCopy the code

Create instance object obj

NSObject *obj = [[NSObject alloc] init];
Copy the code

Converting the oc code to c++ code, we can see that the underlying structure of NSObject is:

struct NSObject_IMPL {
    Class isa;
};
Copy the code

2. The size of memory occupied by the instance object

NSObject is eventually converted to a structure with just a structure pointer to the object inside. So the NSObject object actually only uses 8 bytes of class storage Pointers, but the system actually allocates 16 memory Spaces

NSLog(@"%zd",class_getInstanceSize([NSObject class])); / / the whole structure of 16 (system of the actual distribution) NSLog (@ % lh-zd, malloc_size (const __bridge (* * * * * * * * * * void * * *) (obj)));Copy the code

By reading the source code, we know that the system allocates 16 bytes of memory whenever an object is created with less than 16 bytes of memory, which is apple’s policy.

     size_t instanceSize(size_t extraBytes) {
        size_t size = alignedInstanceSize() + extraBytes;
        // CF requires all objects be at least 16 bytes.
        if (size < 16) size = 16;
        return size;
    }
Copy the code

Sizeof, class_getInstanceSize, malloc_size

  • Sizeof:

Is an operator that gets the size of a type (int, size_t, struct, pointer variable, etc.) at compile time

  • Class_getInstanceSize:

Is a function that is obtained only when the program is running. The size of the memory used by the created object plus all the instance variables is generally aligned with [8]

  • Malloc_size:

Memory allocated by malloc in Mac and iOS is always a multiple of [16]

Objc_getClass and object_getClass

  1. Class objc_getClass(const char *aClassName)
  • Pass in the string class name

  • Returns the corresponding class object

  1. Class object_getClass(id obj)

1) The obj passed in May be an instance object, a class object, a meta-class object

2) Return value

  • If it is an instance object, return a class object

  • If it is a class object, return a meta-class object

  • If it is a meta-class object, return the meta-class object of NSObject

  1. -(Class)class,+(Class)class
  • The class object is returned, no matter how many times it is called

5. Example verification

1, A Person class inherits NSObject and has two ints

struct Person_IMPL { Class isa; //8 int _age; //4 int _height; / / 4}; @interface Person : NSObject { @public int _age; int _height; } @end Person *per = [[Person alloc] init]; per->_age = 18; per->_height = 170; // 18 170 NSLog(@"%d, %d", per->_age, per->_height); // 16 16 NSLog(@"%zd %zd",class_getInstanceSize([Person class]), malloc_size(( **__bridge** **const** **void** *)(per)));Copy the code

The Student class inherits from Person, and Person inherits from NSObject.

@interface Person : NSObject
{
    @public
    int _age;
    int _height;
}
@end
@interface Student : Person
{
    @public
    int _score;
}
@end
Copy the code

The transformed structure is as follows:

struct NSObject_IMPL { Class isa; }; struct Person_IMPL { // struct NSObject_IMPL NSObject_IVARS; Class isa; int _age; int _height; }; struct Student_IMPL { // struct Person_IMPL Person_IVARS; Class isa; //8 int _age; // 4 int _height; // 4 int _score; / / 4};Copy the code

Validation:

Student *stu = [[Student alloc] init]; stu->_age = 20; stu->_height = 180; stu->_score = 85; // 20 180 NSLog(@"%d, %d, %d", stu->_age, stu->_height, stu->_score); NSLog(@"%zd",class_getInstanceSize([Student class])); NSLog(@"%zd",class_getInstanceSize([Student class])); / / 32 system allocation NSLog (@ % lh-zd, malloc_size (const __bridge (* * * * * * * * * * void * * *) (stu)));Copy the code

The Stu object actually needs 20. According to the class_getInstanceSize memory alignment principle [8], it needs 24. Malloc_size is a multiple of the required space according to the system allocation principle [16], so the result is 32

2. Classification of OC objects

Objects in object-C, or OC objects for short, can be divided into three main types:

  • Instance object (instance object)
  • Class object (Class object)
  • Meta-class objects (metaclass objects)

1. Instance object

An instance object is an object that comes out of alloc, and every time you call alloc, you create a new instance object

NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];
Copy the code

Object1, object2 are instance objects of NSObject.

They are two different objects occupying two different pieces of memory

The instance object stores information in memory including:

  • Isa pointer
  • Other member variables

Class object

Classes are also stored in memory as objects of type: Class type; Create:

NSObject *object1 = [[NSObject alloc] init]; NSObject *object2 = [[NSObject alloc] init]; // The class method always returns the class object no matter how many times you call class classObj = [[object1 class] class]; Class objectClass1 = [object1 class]; Class objectClass2 = [object1 class]; Class objectClass3 = object_getClass(object1); Class objectClass4 = object_getClass(object1); Class objectClass5 = [NSObject class]; NSLog(@"%p, %p",object1,object2); // The addresses of these five class objects are the same NSLog(@"%p,%p,%p,%p,%p,%p",classObj,objectClass1,objectClass2,objectClass3,objectClass4,objectClass5);Copy the code

Each class has only one class object in memory with the same address. Class objects store information in memory mainly including:

  1. Isa pointer
  2. Superclass pointer
  3. Class property information (@Property)
  4. Class object method information (method instance method starting with – sign)
  5. Class protocol information (Protocol)
  6. Class member variable information (refers to the description of the member variable, such as which variables, what type, not the specific variable value of the instance object)

The essential structure of a class object

3, Meta-class object (metaclass object)

Class objectMetaClass = object_getClass([NSObject class]);
NSLog(@"%p",objectMetaClass);
Copy the code

ObjectMetaClass is the metaclass of NSObject, and there is only one metaclass per class in memory. Metaclass and class object are very similar in structure. The main information that metaclass objects store in memory is:

  1. Isa pointer
  2. Superclass pointer
  3. Class methods (methods starting with a + sign)

The object_getClass method is used to obtain both metaclass objects and class objects

By looking at the source code, we can see that object_getClass determines whether it’s a class object or an instance object and returns a class object if it’s an instance object and a metaclass object if it’s a class object

You can use the following function to determine whether an object is a metaclass

BOOL result = class_isMetaClass(classObj); //no
BOOL result2 = class_isMetaClass(objectMetaClass); //yes
Copy the code

So alloc creates instance objects and object_getClass creates metaclass objects and other objects are class objects but there is only one class object and there is only one metaclass object and all three classes have isa Pointers, so what does this ISA pointer point to?

Isa and Superclass

1. Isa pointer

1) Isa pointing relation among three types of objects

All three types of objects contain ISA Pointers. The relationship between ISA Pointers is as follows

The isa of the instance object points to the class object. The ISA of the class object points to the metaclass object. The ISA of the metaclass object points to the metaclass object. Similarly, when a class method is called, the class method is stored in the metaclass object. The class object will find the metaclass object through isa pointer, and read the class method in the list of class methods to call.

Note: The ISA pointer to meta-class points to the meta-class of the base class

2) The isa pointer address of the object

The isa pointer to the class object is the same as the address of the class object. However, starting from 64bit, ISA needs to perform a bit operation (&ISA_mask) to calculate the real address.

Check the oc source opensource.apple.com/tarballs/ob… You can see the definition of ISA_MASK

define ISA_MASK        0x0000000ffffffff8ULL
Copy the code

Superclass pointer

In both class and metaclass objects, there is a superclass pointer that points to the superclass object in a similar way

1) Superclass pointer in class object:

For example, now you have a Person object that inherits from NSObject and a Student that inherits from Person and when the studen instance object calls the object method,

  1. First, the instance object looks for the corresponding method in the class object according to its ISA pointer
  2. Student’s superclass pointer to Person’s superclass pointer to Person’s superclass pointer to Person’s superclass pointer.
  3. If not, the Person class object will look in NSObject’s class object based on its superclass pointer.

2) Superclass Pointers in metaclass objects

Also directs the class object to find the corresponding class method in the parent class object:

In the example above, the Student class wants to call a class method,

  1. Student’s metaclass object looks for a method in Student’s metaclass object based on isa
  2. If not, Student’s metaclass will use its superclass pointer to look for a corresponding class method in the parent metaclass (Person’s metaclass).
  3. If it doesn’t, the Person metaclass will look for it in NSObject’s metaclass based on its superclass pointer and call it
  4. If not, NSObject’s metaclass will use the superclass pointer to look in NSObject’s class object to see if there’s an object method with the same name. (We’ll talk more about why the superclass pointer to the base class points to the corresponding class object below.)

3) ISA, Superclass summary

  • Instance isa points to class

  • Class’s ISA points to meta-class

  • The ISA of the meta-class points to the meta-class of the base class

  • The superclass of class points to the superclass of its parent (if there is no superclass, the superclass pointer is nil)

  • The superclass of the meta-class points to the superclass of the superclass.

  • Instance calls the trace of an object’s method (isa finds class, superclass finds parent).

  • Class calls the trace of a class’s method (isa finds meta-class, superclass does not exist).