http://xiongzenghuidegithub.github.io/blog/2016/05/16/kvo-part1/
對KVO的大致實現(xiàn)做個最終總結(jié):
第一步挽牢、當(dāng)一個對象的屬性添加了屬性觀察者之后谱煤,這個對象的 isa指針會被修改
注意: 是這個對象的isa指針,而不是這個對象所屬類的isa指針
第二步禽拔、由runtime在運行時創(chuàng)建出一個對象所屬類的一個子類刘离,名字的格式是NSKVONotifying_原始類名
第三步、重寫原來父類中被觀察屬性property的setter方法實現(xiàn)
class_addMethod()
class_replaceMethod()
// 大致格式如下
- (void)setType:(NSSting *)type {
//1. 調(diào)用父類Cat設(shè)置屬性值的方法實現(xiàn)
[super setType:type];
//2. 通知Cat對象的觀察者執(zhí)行回調(diào)(從斷點效果看是同步執(zhí)行的)
[cat對象的觀察者 observeValueForKeyPath:@"type"? ofObject:self? change:@{}? context:nil];
}
第四步奏赘、對象的 isa指針寥闪,由runtime系統(tǒng)替換指向為第二步中創(chuàng)建的中間類NSKVONotifying_原始類名
第五步、當(dāng)對象的被觀察屬性值發(fā)生改變時(中間類的setter方法實現(xiàn)被調(diào)用)磨淌,就會回調(diào)執(zhí)行觀察者的observeValueForKeyPath: ofObject:change:context:方法實現(xiàn)
從斷點調(diào)用來看疲憋,這個回調(diào)過程是同步執(zhí)行的
第六步,如下兩個方法的返回的objc_class結(jié)構(gòu)體實例是不同的
object_getClass(被觀察者對象) >>> 返回的是替換后的中間類
[被觀察對象 class] >>> 仍然然會之前的原始類
第七步梁只、當(dāng)對象移除屬性觀察者之后缚柳,該對象的isa指針又會恢復(fù)指向為原始類