現(xiàn)在有一個(gè)Person
對(duì)象
@interface Person : NSObject
@property (copy, nonatomic) NSString *name;
@end
通過(guò)KVO或者RAC對(duì)其監(jiān)聽(tīng)后,分別執(zhí)行下面的代碼
- 外面設(shè)置
name
// 1
_person.name = @"Jack";
// 2
[_person setValue:@"Jack" forKey:@"name"];
// 3
[_person setValue:@"Jack" forKey:@"_name"];
- 內(nèi)部設(shè)置
name
// 4
self.name = @"Jack";
// 5
_name = @"Jack";
// 6
[self setValue:@"Jack" forKey:@"name"];
// 7
[self setValue:@"Jack" forKey:@"_name"];
- runtime設(shè)置
name
unsigned int outCount = 0;
Ivar *ivars = class_copyIvarList([Person class], &outCount);
for (int i = 0; i < outCount; i++) {
Ivar ivar = ivars[i];
if ([[NSString stringWithUTF8String:ivar_getName(ivar)] isEqualToString:@"_name"]) {
// 8
object_setIvar(_person, ivar, @"Jack");
}
}
結(jié)果:1植酥、2阻桅、4、6會(huì)觸發(fā)監(jiān)聽(tīng)慨削,而3洞渔、5、7缚态、8不會(huì)觸發(fā)磁椒。
原因:KVO的本質(zhì)是通過(guò)isa-swizzling
新建了一個(gè)子類,并且重寫了屬性的setter
方法玫芦,在setter
方法的頭和尾分別執(zhí)行了willChangeValueForKey:
和didChangevlueForKey:
兩個(gè)方法來(lái)實(shí)現(xiàn)監(jiān)聽(tīng)的浆熔。
因?yàn)?、2桥帆、4医增、6會(huì)走setter
方法,而3老虫、5叶骨、7、8直接設(shè)置name
屬性祈匙,并沒(méi)有走setter
方法忽刽,所以無(wú)法觸發(fā)監(jiān)聽(tīng)。
我們?cè)谑褂肒VC時(shí)菊卷,key
加不加_
決定了是否走setter
方法缔恳。
RAC的監(jiān)聽(tīng)機(jī)制應(yīng)該也是和KVO一樣,所以如果是使用3的方法設(shè)置是不會(huì)觸發(fā)監(jiān)聽(tīng)的洁闰。
拓展:如何監(jiān)聽(tīng)數(shù)組的變化歉甚?
正常KVO/RAC監(jiān)聽(tīng)數(shù)組時(shí),即使我們修改了數(shù)組的內(nèi)容(這里指修改數(shù)組內(nèi)部的內(nèi)容-增刪改)因?yàn)闆](méi)有觸發(fā)setter
方法所以不會(huì)觸發(fā)監(jiān)聽(tīng)扑眉,最簡(jiǎn)單的就是加一句self.arr = self.arr
就可以觸發(fā)監(jiān)聽(tīng)了纸泄。