博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
isa swizzling
阅读量:6618 次
发布时间:2019-06-25

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

那么,既然是isa替换,那主角当然就是isa啦。那么这个技术出现在什么场景呢?其实这个技术在官方文档中关于KVO的文档中有提到过, 里面说到了,KVO是通过isa-swizzling来实现的。

Automatic key-value observing is implemented using a technique called isa-swizzling.The isa pointer, as the name suggests, points to the object’s class which maintains a dispatch table. This dispatch table essentially contains pointers to the methods the class implements, among other data.When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class. As a result the value of the isa pointer does not necessarily reflect the actual class of the instance.You should never rely on the isa pointer to determine class membership. Instead, you should use the class method to determine the class of an object instance.复制代码

最后一段中也说到了,永远不要用用isa来判断一个类的继承关系,而是应该用class方法来判断类的实例。

看着好像很厉害的技术耶~(双眼bling~bling~发光)。那么为了验证这个技术真正的实现了,也就是isa替换了,我们写了下面一段代码来验证。大家一起来观摩一下:

//这里用来说明printInfo方法都做了说明@implementation Person(void)printInfo { NSLog(@”isa:%@,supperclass:%@”,NSStringFromClass(object_getClass(self)),class_getSuperclass(object_getClass(self))); NSLog(@”self:%@, [self superclass]:%@”, self, [self superclass]); NSLog(@”age setter function pointer:%p”, class_getMethodImplementation(object_getClass(self), @selector(setAge:)));NSLog(@”name setter function pointer:%p”, class_getMethodImplementation(object_getClass(self), @selector(setName:)));NSLog(@”printInfo function pointer:%p”, class_getMethodImplementation(object_getClass(self), @selector(printInfo)));}@end复制代码

// 既然是KVO嘛,那我们就来模拟一个虚假的KVO的情况,并且打印对应的信息

Person *person = [[Person alloc] init];NSLog(@”Before add observer————————————————————————–“);[person printInfo];[person addObserver:self forKeyPath:@”age” options:NSKeyValueObservingOptionNew context:&PrivateKVOContext]; NSLog(@”After add observer————————————————————————–“);[person printInfo];[person removeObserver:self forKeyPath:@”age”]; NSLog(@”After remove observer————————————————————————–“);[person printInfo];复制代码

根据之前一篇中提到,object_getClass其实打印的就是isa指针。

其中第一个Person的实现中,我们打印了isa, supperclass, 两个方法的setter的函数指针以及printInfo的函数指针。而运行代码中分别在添加Observer前,添加Observer以及删除Observer后分别打印出该类的信息。那么输出的结果是什么呢?

Before add observer--------------------------------------------------------------------------isa:Person, supper class:NSObjectself:
, [self superclass]:NSObjectage setter function pointer:0x10fe03c40name setter function pointer:0x10fe03be0printInfo function pointer:0x10fe03a30After add observer--------------------------------------------------------------------------isa:NSKVONotifying_Person, supper class:Personself:
, [self superclass]:NSObjectage setter function pointer:0x10ff04c7fname setter function pointer:0x10fe03be0printInfo function pointer:0x10fe03a30After remove observer--------------------------------------------------------------------------isa:Person, supper class:NSObjectself:
, [self superclass]:NSObjectage setter function pointer:0x10fe03c40name setter function pointer:0x10fe03be0printInfo function pointer:0x10fe03a30复制代码

不对,看看文章的标题,其实在添加KVO之后,isa已经替换成了NSKVONotifying_Person,而根据class_getSuperclass得到的结果竟然是Person, 然后age是使我们KVO需要观察的属性,它的setter函数指针变了。而我们也知道,所谓的OC的消息机制是通过isa去查找实现的,那么我们现在可以进行大胆的猜想:

其实KVO的实现可能是:

  • 添加Observer

通过runtime偷偷实现了一个子类,并且以NSKVONotifying_+类名来命名

将之前那个对象的isa指针指向了这个子类。

重写了观察的对象setter方法,并且在重写的中添加了willChangeValueForKey:以及didChangeValueForKey:

  • 移除Observer

只是简单的将其的isa指向原来的类对象中

然后我们在分析一下, 在真正调用的setAge:的情况下, 根据消息机制我们知道它先通过isa找到对应对象的类, 也就是现在NSKVONotifying_Person, 然后再去找setAge:,由于NSKVONotifying_Person这个对象重写了这个方法, 那么就会直接取当前的实现, 也就是带有willChangeValueForKey:以及didChangeValueForKey:, 那么自然就实现了对KVO的实现了。

最后在看看一幅图吧,稍微总结一下isa-swizzling是搞什么东东:

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

你可能感兴趣的文章
MongoDB安装/配置/启动/命令
查看>>
Meteor笔记
查看>>
设计模式(二)AlertDialog中的建造者模式
查看>>
程序员,同样编程,为何做大数据的月薪竟然比我高出好几万!
查看>>
数据库对比脚本
查看>>
Axios遇到React如何优雅的实现实时搜索
查看>>
Kafka 数据迁移
查看>>
使用 react + koa2 + mysql 开发出一个简洁风格的个人博客
查看>>
追踪解析 Disruptor 源码
查看>>
49. Group Anagrams
查看>>
泛型之泛型方法
查看>>
Rust中文社刊2019-01发布
查看>>
Hide Desktop Icon[AutoHotKey]
查看>>
Data Lake Analytics: 以SQL方式查询Redis数据
查看>>
SpringBoot整合Kotlin构建Web服务
查看>>
Spring MVC常用客户端参数接收方式
查看>>
JavaScript:函数防抖与函数节流
查看>>
响应式布局方案
查看>>
小程序瀑布流效果,解决左右两边高度差距过大的问题
查看>>
聊聊flink JobManager的High Availability
查看>>