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实现方式相关推荐

  1. [iOS]-KVO+KVC

    目录: 参考的博客: KVO 什么是KVO KVO的基本使用 KVO使用注意事项 手动调用KVO KVO本质 NSKVONotifying_Apple内部实现 setter的实现不同 KVO部分相关问 ...

  2. 终于明白那些年知其然而不知其所以然的iOS内存管理方式

    终于明白那些年知其然而不知其所以然的iOS内存管理方式 前言 从我开始学习iOS的时候,身边的朋友.网上的博客都告诉我iOS的内存管理是依靠引用计数的,然后说引用计数大于1则对象保存在内存的堆中而引用 ...

  3. 微信公众号内下载pdf等文件,受微信所限制,安卓和IOS不同处理方式(最最最优版)

    继上一篇文章微信公众号内下载pdf等文件,受微信所限制,安卓和IOS不同处理方式 后觉得还有更好的解决办法,这次真的找到更加优化版本,一定需要后台配合才行:后台接口返回Blob,后端设置respons ...

  4. iOS crash 定位方式

    文章目录 iOS crash 定位方式 1. symbolicatecrash 定位 2. atos 定位 iOS crash 定位方式 1. symbolicatecrash 定位 在iOS 中系统 ...

  5. iOS KVO和KVC介绍

    iOS KVO和KVC介绍 KVO和KVC都是基于对NSObject的扩展来实现的,所有继承于NSObject的子类都能使用KVO和KVC. 用来测试的model: @interface User : ...

  6. iOS In House方式发布

    这两天In House签名的时候,提示SSL证书过期了.又折腾了一把iOS In House方式发布.这里开一篇文章记录一下过去折腾In House的经过,未来再修改也更新在这里. 最早在12年的时候 ...

  7. iOS用什么方式实现对一个对象的KVO?(KVO的本质是什么?)

    先给答案,我们再探具体: 利用RuntimeAPI动态生成一个子类,并且让instance对象的isa指向这个全新的子类 当修改instance对象的属性时,会调用Foundation的_NSSetX ...

  8. IOS —— KVO的一个小封装

    不偷懒,不偷懒.今天带来一个KVO封装,以及封装过程中捡起来的知识 那么首先,KVO是什么呢? Key - Value - Observer 的缩写,意为键值对的观察. 实际上的作用就是用来观察键值对 ...

  9. ios kvo 要引入_iOS中KVO的使用

    KVO,全称为Key-Value Observing,是iOS中的一种设计模式,用于检测对象的某些属性的实时变化情况并作出响应.网上广为流传普及的一个例子是利用KVO检测股票价格的变动,例如这里.这个 ...

  10. ios kvo 要引入_iOS:KVO

    本文仅是记录自己在学习的过程中的理解:如有错误,还望各位大佬指正,THX. KVO全称KeyValueObserving,是苹果提供的一套事件通知机制.允许对象监听另一个对象特定属性的改变,并在改变时 ...

最新文章

  1. JavaScript中的递归
  2. java什么是函数式编程,Java 函数式编程(一)初识篇
  3. C#中小数点后保留两位小数,四舍五入的函数及使用方法
  4. c++11-std::functionbind
  5. Oracle存储过程--案例
  6. Matlab制作朱利表
  7. 游戏理论研究四:RPG游戏
  8. 九问国产操作系统,九大掌门人万字回应!
  9. Lua 正确的尾调用(proper tail call)
  10. 工业相机选型和镜头焦距计算
  11. deepstream imagedata multistream 中文注释数据流
  12. C# xml转json(xml、json相互转换)
  13. 机器人无人车项目开发学习 上下位机软硬结合python jetson nano ros
  14. 如何删除难卸载的软件
  15. Pipeline并行处理模型
  16. 什么样的电子签名有法律效力
  17. 常见的生物识别技术有哪些
  18. 讲道理,只要你是一个爱折腾的程序员,毕业找工作真的不需要再花钱培训!
  19. mac远程控制程序:AnyDesk for Mac
  20. ElasticSearch 参数调优

热门文章

  1. M1支持 Accusonus ERA Bundle for mac(音频降噪消除去混音插件包)
  2. FabFilter Total Bundle 2021 for Mac(经典音频效果器合集)
  3. 如何清除 MacBook 上的浏览​​器缓存
  4. 苹果向开发者发布iOS/iPadOS 14.6的第二个测试版
  5. 视频剪辑软件Movie Studio安装教程
  6. Mac mysql 忘记 root 密码,phpmyadmin 登录 No such file or directory 错误处理
  7. 【Flutter】微信项目实战【03】我的界面搭建(下)
  8. CSS按钮动画(四)
  9. PHP之Smarty模板学习
  10. 如何用EasyRecovery恢复中毒U盘中丢失的文件