博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Objective-C 类与实例调用 self 方法的区分
阅读量:4297 次
发布时间:2019-05-27

本文共 2524 字,大约阅读时间需要 8 分钟。

Objective-C 类与实例调用 self 方法的区分

声明一个 Person 类,考虑如下代码:

id aa = [Person self];id bb = [self self];Person *cc = self;id dd = [cc self];

我们知道在 <NSObject> 协议中声明有实例方法:- (instancetype)self;,但是并没有 self 类方法。

那么调用类方法 self 为什么不会出错,将上面的代码转为 C 语言,如下:

id aa = ((id (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("self"));id bb = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("self"));Person *cc = self;id dd = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)cc, sel_registerName("self"));

可见,类方法 self 的调用,实际是向 Class 类对象发送了一个 self 消息,使用下面的方法,获取 self 方法在实例与类中的实现。

Method method1 = class_getClassMethod(object_getClass(Person.class), @selector(self));IMP imp1 = method_getImplementation(method1);    Method method2 = class_getClassMethod(object_getClass(self.class), @selector(self));IMP imp2 = method_getImplementation(method2);    Method method3 = class_getClassMethod(object_getClass(self), @selector(self));IMP imp3 = method_getImplementation(method3);

使用 po 命令,打印得到的结果均如下:

(libobjc.A.dylib`+[NSObject self])
Method method1 = class_getInstanceMethod(object_getClass(Person.class), @selector(self));IMP imp1 = method_getImplementation(method1);    Method method2 = class_getInstanceMethod(object_getClass(self.class), @selector(self));IMP imp2 = method_getImplementation(method2);    Method method3 = class_getInstanceMethod(object_getClass(self), @selector(self));IMP imp3 = method_getImplementation(method3);

使用 po 命令,打印得到的结果均如下:

(lldb) po imp1(libobjc.A.dylib`+[NSObject self])(lldb) po imp2(libobjc.A.dylib`+[NSObject self])(lldb) po imp3(libobjc.A.dylib`-[NSObject self])

从上面的结果来看,就明白为何将类对象称为元类的实例了。

self.class、Person.class、object_getClass(self) 获取的都是描述 Person 类的 Class 类对象,

其中包含了实例所包含的属性及方法。

而 object_getClass(self.class)、object_getClass(Person.class) 得到的是描述 Class 类对象的 Class 元类对象,

其中包含了类属性及类方法。

换言之,get_getClass() 函数总是获取参数的描述对象,而 class 方法,则只是返回调用者的类对象。

去 NSObject 中查找 self 方法,如下:

[self printClassMethod:object_getClass(NSObject.class)];    NSObject *object = [[NSObject alloc]init];[self printClassMethod:object_getClass(object)];- (void)printClassMethod:(Class)class {    unsigned int count;    Method *list = class_copyMethodList(class, &count);    NSLog(@"===count : %d===",count);    for (int i = 0; i < count; i++) {        SEL name = method_getName(*(list+i));        NSLog(@"%s",sel_getName(name));    }}

此次测试打印的数量如下:

===count : 114======count : 355===

最终结果显示,NSObject 中是存在类方法 self 的,这也是 [Person self] 能够编译执行的原因。

实际 [Person self] 等同于 [Person class]

运行时的相关方法可以参考 。

转载地址:http://ovdws.baihongyu.com/

你可能感兴趣的文章
学习笔记_vnpy实战培训day02
查看>>
学习笔记_vnpy实战培训day03
查看>>
VNPY- VnTrader基本使用
查看>>
VNPY - CTA策略模块策略开发
查看>>
VNPY - 事件引擎
查看>>
MongoDB基本语法和操作入门
查看>>
学习笔记_vnpy实战培训day04_作业
查看>>
OCO订单(委托)
查看>>
学习笔记_vnpy实战培训day05
查看>>
学习笔记_vnpy实战培训day06
查看>>
聚合搜索引擎
查看>>
Python super钻石继承
查看>>
回测引擎代码分析流程图
查看>>
Excel 如何制作时间轴
查看>>
股票网格交易策略
查看>>
matplotlib绘图跳过时间段的处理方案
查看>>
vnpy学习_04回测评价指标的缺陷
查看>>
ubuntu终端一次多条命令方法和区别
查看>>
python之偏函数
查看>>
vnpy学习_06回测结果可视化改进
查看>>