iOS-classobject_getClassobjc_getClassobjc_getMetaClass区别
Posted MinggeQingchun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS-classobject_getClassobjc_getClassobjc_getMetaClass区别相关的知识,希望对你有一定的参考价值。
在Objective-C的类型结构中,有几个比较重要的概念:Object(实例),Class(类),Metaclass(元类),Rootclass(根类),Rootclass‘s metaclass(根元类),且这些都是对象。
对于class、object_getClass、objc_getClass这三种方法,全部返回CLass类对象;objc_getMetaClass方法返回元类对象。
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{
//转换字符串类别
const char * 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);
}
输出结果如下:
p/x:以十六进制输出
综上:
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-classobject_getClassobjc_getClassobjc_getMetaClass区别的主要内容,如果未能解决你的问题,请参考以下文章