iOS KVO实现方式
2019独角兽企业重金招聘Python工程师标准>>>
KVO 也许是iOS中“最神奇”的部分了,因为你不需要在被观察对象中添加任何代码,就可以实现对被观察对象属性改变的通知。KVO究竟是怎么实现的?
KVO是通过Objective-C的runtime来实现的。当你第一次要对一个对象进行观察时,runtime会为你创建一个被观察对象class的subclass。在这个新创建的subclass中,KVO会复写所要观察属性的setter方法,然后转换被观察对象的isa指针,指向新创建的subclass,所以,你想要观察的对象,变成了KVO在runtime时创建的subclass。因为Apple不想让这种机制暴露,所以还会复写要观察对象的class方法,所以,当你调用class来判断该对象的class时,还会显示原对象的class类型,而不是subclass的类型。
继续探究
// gcc -o kvoexplorer -framework Foundation kvoexplorer.m#import <Foundation/Foundation.h>#import <objc/runtime.h>@interface TestClass : NSObject{int x;int y;int z;}@property int x;@property int y;@property int z;@end@implementation TestClass@synthesize x, y, z;@endstatic NSArray *ClassMethodNames(Class c){NSMutableArray *array = [NSMutableArray array];unsigned int methodCount = 0;Method *methodList = class_copyMethodList(c, &methodCount);unsigned int i;for(i = 0; i < methodCount; i++)[array addObject: NSStringFromSelector(method_getName(methodList[i]))];free(methodList);return array;}static void PrintDescription(NSString *name, id obj){NSString *str = [NSString stringWithFormat:@"%@: %@\n\tNSObject class %s\n\tlibobjc class %s\n\timplements methods <%@>",name,obj,class_getName([obj class]),class_getName(obj->isa),[ClassMethodNames(obj->isa) componentsJoinedByString:@", "]];printf("%s\n", [str UTF8String]);}int main(int argc, char **argv){[NSAutoreleasePool new];TestClass *x = [[TestClass alloc] init];TestClass *y = [[TestClass alloc] init];TestClass *xy = [[TestClass alloc] init];TestClass *control = [[TestClass alloc] init];[x addObserver:x forKeyPath:@"x" options:0 context:NULL];[xy addObserver:xy forKeyPath:@"x" options:0 context:NULL];[y addObserver:y forKeyPath:@"y" options:0 context:NULL];[xy addObserver:xy forKeyPath:@"y" options:0 context:NULL];PrintDescription(@"control", control);PrintDescription(@"x", x);PrintDescription(@"y", y);PrintDescription(@"xy", xy);printf("Using NSObject methods, normal setX: is %p, overridden setX: is %p\n",[control methodForSelector:@selector(setX:)],[x methodForSelector:@selector(setX:)]);printf("Using libobjc functions, normal setX: is %p, overridden setX: is %p\n",method_getImplementation(class_getInstanceMethod(object_getClass(control),@selector(setX:))),method_getImplementation(class_getInstanceMethod(object_getClass(x),@selector(setX:))));return 0;}
首先,定义一个TestClass,有3个属性。
然后定义一些工具函数。ClassMethodNames 通过Objective-C 的runtime函数,来返回当前class实现的方法名。
代码执行结果
control: <TestClass: 0x104b20> NSObject class TestClass libobjc class TestClass implements methods <setX:, x, setY:, y, setZ:, z>
x: <TestClass: 0x103280> NSObject class TestClass libobjc class NSKVONotifying_TestClass implements methods <setY:, setX:, class, dealloc, _isKVOA>
y: <TestClass: 0x104b00> NSObject class TestClass libobjc class NSKVONotifying_TestClass implements methods <setY:, setX:, class, dealloc, _isKVOA>
xy: <TestClass: 0x104b10> NSObject class TestClass libobjc class NSKVONotifying_TestClass implements methods <setY:, setX:, class, dealloc, _isKVOA>
Using NSObject methods, normal setX: is 0x195e, overridden setX: is 0x195e
Using libobjc functions, normal setX: is 0x195e, overridden setX: is 0x96a1a550
可以看出,
0)TestClass 在runtime时变成了NSKVONotifying_TestClass
1)虽然x,y只观察了一个属性,但是NSKVONotifying_TestClass却实现了setY, setX方法。也就是说,一个类,KVO只会subclass一个KVO类,也就是NSKVONotifying_TestClass类。
2)NSKVONotifying_TestClass 覆写了class方法,来掩盖subclass的存在,还覆写了dealloc方法。除此之外,还有一个新的方法_isKVOA, 是Apple提供的一个私有方法,用于判断一个object是否生成动态subclass。
原文链接:http://www.mikeash.com/pyblog/friday-qa-2009-01-23.html
转载于:https://my.oschina.net/u/566401/blog/179485
iOS KVO实现方式相关推荐
- [iOS]-KVO+KVC
目录: 参考的博客: KVO 什么是KVO KVO的基本使用 KVO使用注意事项 手动调用KVO KVO本质 NSKVONotifying_Apple内部实现 setter的实现不同 KVO部分相关问 ...
- 终于明白那些年知其然而不知其所以然的iOS内存管理方式
终于明白那些年知其然而不知其所以然的iOS内存管理方式 前言 从我开始学习iOS的时候,身边的朋友.网上的博客都告诉我iOS的内存管理是依靠引用计数的,然后说引用计数大于1则对象保存在内存的堆中而引用 ...
- 微信公众号内下载pdf等文件,受微信所限制,安卓和IOS不同处理方式(最最最优版)
继上一篇文章微信公众号内下载pdf等文件,受微信所限制,安卓和IOS不同处理方式 后觉得还有更好的解决办法,这次真的找到更加优化版本,一定需要后台配合才行:后台接口返回Blob,后端设置respons ...
- iOS crash 定位方式
文章目录 iOS crash 定位方式 1. symbolicatecrash 定位 2. atos 定位 iOS crash 定位方式 1. symbolicatecrash 定位 在iOS 中系统 ...
- iOS KVO和KVC介绍
iOS KVO和KVC介绍 KVO和KVC都是基于对NSObject的扩展来实现的,所有继承于NSObject的子类都能使用KVO和KVC. 用来测试的model: @interface User : ...
- iOS In House方式发布
这两天In House签名的时候,提示SSL证书过期了.又折腾了一把iOS In House方式发布.这里开一篇文章记录一下过去折腾In House的经过,未来再修改也更新在这里. 最早在12年的时候 ...
- iOS用什么方式实现对一个对象的KVO?(KVO的本质是什么?)
先给答案,我们再探具体: 利用RuntimeAPI动态生成一个子类,并且让instance对象的isa指向这个全新的子类 当修改instance对象的属性时,会调用Foundation的_NSSetX ...
- IOS —— KVO的一个小封装
不偷懒,不偷懒.今天带来一个KVO封装,以及封装过程中捡起来的知识 那么首先,KVO是什么呢? Key - Value - Observer 的缩写,意为键值对的观察. 实际上的作用就是用来观察键值对 ...
- ios kvo 要引入_iOS中KVO的使用
KVO,全称为Key-Value Observing,是iOS中的一种设计模式,用于检测对象的某些属性的实时变化情况并作出响应.网上广为流传普及的一个例子是利用KVO检测股票价格的变动,例如这里.这个 ...
- ios kvo 要引入_iOS:KVO
本文仅是记录自己在学习的过程中的理解:如有错误,还望各位大佬指正,THX. KVO全称KeyValueObserving,是苹果提供的一套事件通知机制.允许对象监听另一个对象特定属性的改变,并在改变时 ...
最新文章
- JavaScript中的递归
- java什么是函数式编程,Java 函数式编程(一)初识篇
- C#中小数点后保留两位小数,四舍五入的函数及使用方法
- c++11-std::functionbind
- Oracle存储过程--案例
- Matlab制作朱利表
- 游戏理论研究四:RPG游戏
- 九问国产操作系统,九大掌门人万字回应!
- Lua 正确的尾调用(proper tail call)
- 工业相机选型和镜头焦距计算
- deepstream imagedata multistream 中文注释数据流
- C# xml转json(xml、json相互转换)
- 机器人无人车项目开发学习 上下位机软硬结合python jetson nano ros
- 如何删除难卸载的软件
- Pipeline并行处理模型
- 什么样的电子签名有法律效力
- 常见的生物识别技术有哪些
- 讲道理,只要你是一个爱折腾的程序员,毕业找工作真的不需要再花钱培训!
- mac远程控制程序:AnyDesk for Mac
- ElasticSearch 参数调优
热门文章
- M1支持 Accusonus ERA Bundle for mac(音频降噪消除去混音插件包)
- FabFilter Total Bundle 2021 for Mac(经典音频效果器合集)
- 如何清除 MacBook 上的浏览​​器缓存
- 苹果向开发者发布iOS/iPadOS 14.6的第二个测试版
- 视频剪辑软件Movie Studio安装教程
- Mac mysql 忘记 root 密码,phpmyadmin 登录 No such file or directory 错误处理
- 【Flutter】微信项目实战【03】我的界面搭建(下)
- CSS按钮动画(四)
- PHP之Smarty模板学习
- 如何用EasyRecovery恢复中毒U盘中丢失的文件