IOS class method and objc_getClass method

According to the previous blog iOS-class,object_getClass,objc_getClass,objc_getMetaClass differences The main findings are class method and objc_ The difference between getClass method and objc method, so this article mainly describes the class method and objc method_ GetClass method.

1, Object (objc instance object), Class (Class), Metaclass (Metaclass), Rootclass (root Class), Rootclass's Metaclass (root Metaclass)

First, let's talk about several data structures of classes in Objective-C; In the type structure of Objective-C, Object (instance), Class (Class), Metaclass (Metaclass), Rootclass (root Class), Rootclass's Metaclass (root Metaclass), and these are objects.

We can use two diagrams to understand the relationship diagrams in the above types

1. Classic object model diagram of Objective-C

2,   Relationships among instance objects, classes, and metaclasses

Instance object: an object or instance objc we create is actually a struct objc_object structure. This structure has only one member variable. This is a Class variable isa and a structure pointer. The isa pointer of this objc object points to its Class object (that is, the Class we usually call)

CLass: stores data related to Object instances, such as instance method list, member variable list, and attribute list.

Metaclass: stores Class related data, such as Class method list, Class information, etc.

Refer to Apple's official open source code

objc4 source code online browsing

objc4 source code download

2, class method and objc_getClass method

1. class method

Example method-   (CLass)class;

Class method + (classes) class

In Apple's official objc source code, NSObject.mm file:

// Class method that returns itself
+ (Class)class {
    return self;
}
 
// Instance method, find isa (class)
- (Class)class {
    return object_getClass(self);
}

2,object_getClass method

object_getClass(id _Nullable obj) 

(1) Pass in parameters: obj may be an instance object, a class object, or a meta class object

(2) Return value:

[1] If it is an instance object, the class object is returned

[2] If it is a class object, the meta class object is returned

[3] If it is a meta class object, return the meta class object of NSObject (base class)

Official source code:

/***********************************************************************
* object_getClass.
* Locking: None. If you add locking, tell gdb (rdar://7516456).
**********************************************************************/
Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}

3, objc object type

We first pass objc_ The getClass method obtains the isa pointer, that is, the pointer to the class object

objc_ The getmetaclass method obtains the isa pointer in the class object, that is, the pointer to the metaclass object

The code is as follows:

Class c1 = objc_getClass("People");
Class c2 = objc_getMetaClass("People");
    
NSLog(@"objc_getClass----              %p",c1);
NSLog(@"objc_getMetaClass----          %p",c2);

Output results:

1. obj is an instance object

In Object-C, object is essentially a struct. In this struct, a pointer named isa will be saved, and the pointer will point to the class of the object. The definitions are as follows:

/// Represents an instance of a class.
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};
/// A pointer to an instance of a class.
typedef struct objc_object *id;

When we initialize an instance of a class, we can directly define it with id, and the id is defined as above. Therefore, after the initialization of an instance of a class, there is an isa pointer inside it, and this pointer type points to struct   objc_ The structure of class actually points to the class to which this instance belongs.

The code is as follows:

    //obj is an instance object
    id obj = [[People alloc]init];
    People *people = obj;
    
    /*----obj Is an instance object----*/
    Class cls = [obj class];
    Class cls2 = object_getClass(obj);
    Class cls3 = [people class];
    Class cls4 = object_getClass(people);
    NSLog(@"");
    NSLog(@"----obj Is an instance object----");
    NSLog(@"Instance object:class----              %p" , cls);
    NSLog(@"Instance object:object_getClass----    %p" , cls2);
    NSLog(@"Instance object:class----              %p" , cls3);
    NSLog(@"Instance object:object_getClass----    %p" , cls4);

Output results:

When obj is an instance variable

object_ The output results of getClass (obj) and [obj class] always get the isa pointer, that is, the pointer to the class object.  

2. obj is a Class object

In Objective-C, the definition of any class is an object (except for the basic types such as int and char). There is no essential difference between a class and an instance (object) of a class. Any object has an isa pointer.

We open Xcode  < obc/runtime.h>   There is a structure definition in the header file or the runtime. H file of the official objc source code published by apple

struct object_class{
    Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
     Class super_class                        OBJC2_UNAVAILABLE;  // Parent class
     const char *name                         OBJC2_UNAVAILABLE;  // Class name
     long version                             OBJC2_UNAVAILABLE;  // Class version information. The default value is 0
     long info                                OBJC2_UNAVAILABLE;  // Class information, some bit identifiers for runtime use
     long instance_size                       OBJC2_UNAVAILABLE;  // The instance variable size of this class
     struct objc_ivar_list *ivars             OBJC2_UNAVAILABLE;  // Linked list of member variables of this class
     struct objc_method_list *methodLists     OBJC2_UNAVAILABLE;  // Method defined linked list
     struct objc_cache *cache                 OBJC2_UNAVAILABLE;  // Method cache
     struct objc_protocol_list *protocols     OBJC2_UNAVAILABLE;  // Protocol linked list
#endif
}OBJC2_UNAVAILABLE;

This structure is actually what we call it   class   , His   Click the type of Class isa pointer and you will find that it is defined as follows:

// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

The original isa pointer still points to a   objc_class   Structure is just called Class for semantics

The code is as follows:

    //obj is an instance object
    id obj = [[People alloc]init];
    People *people = obj;
    //classObj is a class object
    Class classObj = [obj class];
    
    /*----obj Class object----*/
    Class clsc = [classObj class];
    Class clsc2 = object_getClass(classObj);
    NSLog(@"");
    NSLog(@"----obj Class object----");
    NSLog(@"Class object:class----               %p" , clsc);
    NSLog(@"Class object:object_getClass----     %p" , clsc2);

Output results:

  When obj is a class object

object_getClass(obj) returns the isa pointer in the class object, that is, the pointer to the metaclass object;

[obj class] returns the class object itself

3. obj is a Metaclass (Metaclass) object

Metaclass has the same structure as Class, but different functions.

CLass: stores data related to Object instances, such as instance method list, member variable list, and attribute list.

Metaclass: stores class related data, such as class method list, class information, etc. We can refer to the relationship diagram between header instance Object, class and metaclass

The code is as follows:

    //obj is an instance object
    id obj = [[People alloc]init];
    //classObj is a class object
    Class classObj = [obj class];
    //metaClassObj is a metaclass object
    Class metaClassObj = object_getClass(classObj);
    
    /*----obj Is a metaclass object----*/
    Class clso = [metaClassObj class];
    Class clso2 = object_getClass(metaClassObj);
    NSLog(@"");
    NSLog(@"----obj Is a metaclass object----");
    NSLog(@"metaclass object :class----              %p" , clso);
    NSLog(@"metaclass object :object_getClass----    %p" , clso2);

Output results:

When obj is a Metaclass object

object_getClass(obj) returns the isa pointer in the metaclass object, because the isa pointer of the metaclass object points to the root class, and all returned are the address pointers of the root class object;

[obj class] returns the metaclass itself

4. obj is the Rootclass class (root class) object

Rootclass is the root Class. The isa pointer in the Metaclass of any Class points to the root Class. And the structure is the same as the Class structure.

The code is as follows:

    //obj is an instance object
    id obj = [[People alloc]init];
    //classObj is a class object
    Class classObj = [obj class];
    //metaClassObj is a metaclass object
    Class metaClassObj = object_getClass(classObj);
    //rootClassObj is the root class object
    Class rootClassObj = object_getClass(metaClassObj);
    
    /*----obj Is a root class object----*/
    Class clsr = [rootClassObj class];
    Class clsr2 = object_getClass(rootClassObj);
    NSLog(@"");
    NSLog(@"----obj Is a root class object----");
    NSLog(@"Root class object:class----              %p" , clsr);
    NSLog(@"Root class object:object_getClass----    %p" , clsr2);

Output results:

When obj is a Rootclass object

object_getClass(obj) returns the isa pointer in the root class object, because the isa pointer of the root class object points to Rootclass's metaclass (root metaclass), that is, it returns the address pointer of the root metaclass;

[obj class] returns itself.
Because the isa pointer of the root class actually points to itself, all root metaclasses are actually root classes, and all output results are the same.

  4, Conclusion  

1,object_getClass(obj)

The isa pointer of obj is returned

2,[obj class]

(1) obj is an instance object
The instance method called is: - (Class)class, the isa pointer in the returned obj object;

(2) obj is a class object (including metaclass, root class and root metaclass)
The class method called is + (Class)class, and the returned result is the caller itself.

At this time, let's look back at the object model diagram of Object-C and think about it

1. Create an instance object (People *people) in memory, and create a corresponding class object (Class peopleClass) and metaclass object (Class peopleMeta);

Note: multiple instance objects can be created through calloc, but class objects and metaclass objects have only one copy in memory and are created only once;

2. The essence of objects is actually the structure struct of C language. The memory structure of each object is:

people: isa pointer + only store the value of the member variable of the Person class;

People: isa pointer + superclass pointer + store the type, name, protocol, object method, etc. of member variables;

peopleMeta: isa pointer + superclass pointer + store only class methods;

3. isa points to:

People: points to the class object people;

People: points to the metaclass object peopleMeta;

peopleMeta: refers to the metaclass object meta of the base class (Root, such as NSObject) (isa of the metaclass object of the base class points to the metaclass object itself);

4. superclass points to:

People: the class object pointing to the parent class > > base class points to nil;

peopleMeta: the metaclass object pointing to the parent > > base class points to the class object of the base class;

GitHub sample code Demo

Reference article:

iOS notes -- class method and objc_getClass method

object_ The difference between getClass (obj) and [obj class]

class and object_getClass method difference

Keywords: Class

Added by faswad on Thu, 07 Oct 2021 06:58:19 +0300