iOS-OC|iOS-class、object_getClass、objc_getClass、objc_getMetaClass区别

在Objective-C的类型结构中,有几个比较重要的概念:Object(实例),Class(类),Metaclass(元类),Rootclass(根类),Rootclass‘s metaclass(根元类),且这些都是对象。
对于class、object_getClass、objc_getClass这三种方法,全部返回CLass类对象;objc_getMetaClass方法返回元类对象。
objc4源码在线浏览
objc4源码下载 (本文使用的objc4-818.2版本)
1、class方法
实例方法 - (CLass)class;
类方法 + (Classs)class
在苹果公开的官方objc源码,NSObject.mm文件中:

// 类方法,返回自身 + (Class)class { return self; }// 实例方法,查找isa(类) - (Class)class { return object_getClass(self); }

class方法无论是类对象还是实例对象都可以调用,可以嵌套,返回永远是自身的类对象。如:
Person *p = [[Person alloc]init]; Class *pClass == [p class] == [ [p class]class] == [[ [p class]class]class] == [Person class]

2、object_getClass方法
object_getClass(id _Nullable obj) ;用于获取一个objc对象的isa指针指向的对象(即平时我们所说的类)
(1)传入参数:obj可能是instance实例对象、class类对象、meta-class元类对象
(2)返回值:
【1】如果是instance实例对象,返回class对象
【2】如果是class类对象,返回meta-class对象
【3】如果是meta-class元类对象,返回NSObject(基类)的meta-class对象
官方源码:
/*********************************************************************** * 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; }

/** * Returns the class of an object. * * @param obj The object you want to inspect. * * @return The class object of which \e object is an instance, *or \c Nil if \e object is \c nil. */ OBJC_EXPORT Class _Nullable object_getClass(id _Nullable obj) OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

object_getClass 和 class 同样可以嵌套,但是 object_getClass 得到的是他的 isa 指向的地址。即:
Person *p = [[Person alloc]init]; p->[Person class]->PersonMetaClass->PersonMetaClass(元类的ISA指针是指向自己的)

意思是 p 的 isa 指向 [Person class] ,[Person class] 的 isa 指向 PersonMetaClass
3、objc_getClass方法
objc_getClass(const char * _Nonnull name)
(1)传入参数:字符串类名
(2)返回值:对应的类对象
/* Obtaining Class Definitions *//** * Returns the class definition of a specified class. * * @param name The name of the class to look up. * * @return The Class object for the named class, or \c nil *if the class is not registered with the Objective-C runtime. * * @note \c objc_getClass is different from \c objc_lookUpClass in that if the class *is not registered, \c objc_getClass calls the class handler callback and then checks *a second time to see whether the class is registered. \c objc_lookUpClass does *not call the class handler callback. * * @warning Earlier implementations of this function (prior to OS X v10.0) *terminate the program if the class does not exist. */ OBJC_EXPORT Class _Nullable objc_getClass(const char * _Nonnull name) OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

objc_getClass 无法嵌套,因为参数 是 char 类型,效果和 class 相同(因为不能嵌套,所以和class可以认为是相同的)
4、objc_getMetaClass方法
objc_getMetaClass(const char * _Nonnull name)
(1)传入参数:字符串类名
(2)返回值:对应类的元类对象
/** * Returns the metaclass definition of a specified class. * * @param name The name of the class to look up. * * @return The \c Class object for the metaclass of the named class, or \c nil if the class *is not registered with the Objective-C runtime. * * @note If the definition for the named class is not registered, this function calls the class handler *callback and then checks a second time to see if the class is registered. However, every class *definition must have a valid metaclass definition, and so the metaclass definition is always returned, *whether it’s valid or not. */ OBJC_EXPORT Class _Nullable objc_getMetaClass(const char * _Nonnull name) OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

验证:通过 class_isMetaClass 方法可以验证(判断是否是元类)
/** 判断是否是元类 */ + (void)isMetaClass { /**class_isMetaClass 方法 通过 class_isMetaClass 方法可以验证判断是否是元类 */ Class c1 = object_getClass(self); Class c2 = [self getMetaClassWithChildClass:self]; BOOL object_getClass = class_isMetaClass(c1); BOOL objc_getMetaClass = class_isMetaClass(c2); NSLog(@"object_getClass是否是元类:%@",object_getClass?@"YES":@"NO"); NSLog(@"objc_getMetaClass是否是元类:%@",objc_getMetaClass?@"YES":@"NO"); }/** 获取类的元类 @param childClass 目标类别 @return 返回元类 */ + (Class)getMetaClassWithChildClass:(Class)childClass{ //转换字符串类别 constchar * classChar = [NSStringFromClass(childClass) UTF8String]; //需要char的字符串 获取元类 return objc_getMetaClass(classChar); }

测试代码如下:
- (void)testGetClassP { //实例对象 People *people = [[People alloc]init]; //类对象 Class peopleClass = [people class]; Class c1 = objc_getClass("People"); Class c2 = objc_getMetaClass("People"); //实例对象 Class c3 = [people class]; Class c4 = object_getClass(people); //类对象 Class c5 = [peopleClass class]; Class c6 = object_getClass(peopleClass); NSLog(@"objc_getClass----%p",c1); NSLog(@"objc_getMetaClass----%p",c2); NSLog(@""); NSLog(@"----实例对象----"); //NSLog(@"实例对象:people----%p",people); NSLog(@"实例对象:class----%p",c3); NSLog(@"实例对象:object_getClass---- %p",c4); NSLog(@""); NSLog(@"----类对象----"); //NSLog(@"类对象:peopleClass----%p",peopleClass); NSLog(@"类对象:class----%p",c5); NSLog(@"类对象:object_getClass----%p",c6); }

输出结果如下:
iOS-OC|iOS-class、object_getClass、objc_getClass、objc_getMetaClass区别
文章图片

p/x:以十六进制输出
iOS-OC|iOS-class、object_getClass、objc_getClass、objc_getMetaClass区别
文章图片

综上:
1、objc_getMetaClass 获取元类MetalClass
2、objc_getClass 获取对应类Class
3、object_getClass 获取 object 的isa指针对象
4、class分为
实例方法 - (CLass)class;
类方法 + (Classs)class
看到objc4源码下载上的官方源码:
// 类方法,返回自身 + (Class)class { return self; }// 实例方法,查找isa(类) - (Class)class { return object_getClass(self); }

如果objc为实例对象,则 class方法 和 object_getClass方法一样,获得它的isa指针指向的类对象(即指向类对象的指针,即对应的类)类对象不是元类
如果objc为类对象,则 class方法 获得 调用类本身;object_getClass方法 获取类对象中的isa指针(即指向元类对象的指针,即元类) ,类对象isa指针指向的对象是元类
因此,这4个方法中主要还是class方法和objc_getClass方法,请移步参考iOS-class方法和objc_getClass方法
GitHub示例代码Demo
【iOS-OC|iOS-class、object_getClass、objc_getClass、objc_getMetaClass区别】参考文章
objc_getClass、object_getClass、class区别

    推荐阅读