<strong>驗證<code>KVO</code></strong>
<code>objective-c</code>中的<code>kvo</code>是觀察者模式的一種oc實現(xiàn)。
不管使用方式了亭病,直接看看kvo是如何實現(xiàn)的。
蘋果官方文檔解釋
簡單粗暴的解釋就是,在對一個class 進行kvo監(jiān)聽的時候幔戏,系統(tǒng)內(nèi)部實現(xiàn)了一個子類,繼承自 原先的類税课,然后 替換原先類的 isa指針闲延,重寫set方法,class 方法韩玩。
下面我們驗證一下:
@import ObjectiveC.message;
@import ObjectiveC.runtime;
@interface XXObc : NSObject
@property (nonatomic, copy) NSString *ccc;
@end
@implementation XXObc
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"%@",keyPath);
}
@end
在 main 方法中實現(xiàn)
XXObc *xx = [XXObc new];
[xx addObserver:xx
forKeyPath:@"ccc"
options:NSKeyValueObservingOptionNew
context:nil];
xx.ccc = @"ccccccc";
IMP imp = class_getMethodImplementation(NSClassFromString(@"NSKVONotifying_XXObc"),
@selector(class));
IMP imp1 = class_getMethodImplementation([xx class], @selector(class));
if (imp != imp1) {
NSLog(@"11111");
}
此處 <code> NSKVONotifying_XXObc </code> 就是系統(tǒng)內(nèi)部實現(xiàn)的一個<code>XXObc</code>的子類垒玲。根據(jù)官方文檔的解釋,系統(tǒng)生成<code> NSKVONotifying_XXObc </code>類找颓,然后通過交換原先類的<code>isa</code>指針來實現(xiàn)的KVO,怎么知道<code> NSKVONotifying_XXObc </code>類名的:通過調(diào)用下面方法
po object_getClassName([xx class])
控制臺簡單粗暴的打印合愈。
此處為什么要比較,<code>class</code> 方法的<code>IMP</code>,上面apple的文檔不是說了击狮,不能依賴<code>isa</code> 指針來判斷一個類佛析,要通過<code>class</code> 所以,子類必然是重寫過<code>class</code>方法的彪蓬。
我們自己再創(chuàng)建一個子類寸莫,在<code>addObserver</code>之后修改一下xx的<code>isa</code>指針,看看kvo有沒有效果档冬。
添加如下子類膘茎。
@interface XXXChildObj : XXObc
@end
@implementation XXXChildObj
- (void)setCcc:(NSString *)ccc {
[super setCcc:ccc];
}
@end
調(diào)試代碼稍微修改
XXObc *xx = [XXObc new];
[xx addObserver:xx
forKeyPath:@"ccc"
options:NSKeyValueObservingOptionNew
context:nil];
object_setClass(xx,
[XXXChildObj class]);
xx.ccc = @"ccccccc";
IMP imp = class_getMethodImplementation(NSClassFromString(@"NSKVONotifying_XXObc"),
@selector(class));
IMP imp1 = class_getMethodImplementation([XXXChildObj class], @selector(class));
if (imp != imp1) {
NSLog(@"11111");
}
<code>object_setClass</code>通過這個方法來改變isa指針
這下看到,<code>XXObc</code> 的 <code>observeValueForKeyPath</code> 方法不會再被調(diào)用了酷誓。
系統(tǒng)內(nèi)部實現(xiàn)的子類披坏,比如這里的<code>NSKVONotifying_XXObc</code>。 重寫 class 方法盐数,只是為了麻痹一下開發(fā)者刮萌,隱藏一下實現(xiàn)細節(jié)。也不影響通過 class 方法判斷一下類娘扩,一舉兩得着茸。
以上就是驗證KVO的實現(xiàn)過程。