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);
}
输出结果如下:
文章图片
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-OC|iOS-class、object_getClass、objc_getClass、objc_getMetaClass区别】参考文章
objc_getClass、object_getClass、class区别
推荐阅读
- 一个人的碎碎念
- 野营记-第五章|野营记-第五章 讨伐梦魇兽
- Shell-Bash变量与运算符
- 清明,是追思、是传承、是感恩。
- 牛人进化+|牛人进化+ 按自己的意愿过一生
- 七老修复好敏感、角质层薄、红血丝
- 华为旁!大社区、地铁新盘,佳兆业城市广场五期!
- 标签、语法规范、内联框架、超链接、CSS的编写位置、CSS语法、开发工具、块和内联、常用选择器、后代元素选择器、伪类、伪元素。
- 螃蟹和这些食物同吃,轻则腹泻、重则中毒!要小心哦~
- 八、「料理风云」