從添加觀察者開始
[_p addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
通過Hopper反編譯得到addObserver:forKeyPath的實現
/* @class NSObject */
-(void)addObserver:(void *)arg2 forKeyPath:(void *)arg3 options:(unsigned long long)arg4 context:(void *)arg5 {
os_unfair_recursive_lock_lock_with_options(__NSKeyValueObserverRegistrationLock.llvm.18255262684423441536, 0x0, arg2, arg3, arg4, arg5);
[self _addObserver:arg2 forProperty:_NSKeyValuePropertyForIsaAndKeyPath(object_getClass(self), arg3) options:arg4 context:arg5];
os_unfair_recursive_lock_unlock(__NSKeyValueObserverRegistrationLock.llvm.18255262684423441536);
return;
}
加鎖,解鎖不用說。中間的這句調用了兩個方法:
[self _addObserver:arg2 forProperty:_NSKeyValuePropertyForIsaAndKeyPath(object_getClass(self), arg3) options:arg4 context:arg5];
1._NSKeyValuePropertyForIsaAndKeyPath
2._addObserver:forProperty:
int _NSKeyValuePropertyForIsaAndKeyPath(int arg0, int arg1) {
r14 = rsi;
r15 = rdi;
__NSKeyValueContainerClassForIsa();
if (*_NSKeyValueProperties.llvm.13863498383568664478 != 0x0) {
stack[-80] = 0x0;
rax = CFSetGetValue(*_NSKeyValueProperties.llvm.13863498383568664478, &stack[-80]);
rbx = rax;
if (rax == 0x0) {
rax = *_kCFTypeSetCallBacks;
*(&stack[-128] + 0x18) = *(rax + 0x18);
*(&stack[-128] + 0x10) = *(rax + 0x10);
rcx = *rax;
*(&stack[-128] + 0x8) = *(rax + 0x8);
stack[-128] = rcx;
*(&stack[-128] + 0x20) = _NSKeyValuePropertyIsEqual.llvm.13863498383568664478;
*(&stack[-128] + 0x28) = _NSKeyValuePropertyHash.llvm.13863498383568664478;
rax = CFSetCreateMutable(0x0, 0x0, &stack[-128]);
rbx = _NSKeyValuePropertyForIsaAndKeyPathInner.llvm.13863498383568664478(r15, r14, rax);
CFRelease(rax);
if (0x0 == 0x0) {
if (**___stack_chk_guard == **___stack_chk_guard) {
rax = rbx;
}
else {
rax = __stack_chk_fail();
}
}
else {
rax = objc_exception_rethrow();
}
}
else {
if (**___stack_chk_guard == **___stack_chk_guard) {
rax = rbx;
}
else {
rax = __stack_chk_fail();
}
}
}
else {
rax = *_kCFTypeSetCallBacks;
*(&stack[-128] + 0x18) = *(rax + 0x18);
*(&stack[-128] + 0x10) = *(rax + 0x10);
rcx = *rax;
*(&stack[-128] + 0x8) = *(rax + 0x8);
stack[-128] = rcx;
*(&stack[-128] + 0x20) = _NSKeyValuePropertyIsEqual.llvm.13863498383568664478;
*(&stack[-128] + 0x28) = _NSKeyValuePropertyHash.llvm.13863498383568664478;
rax = CFSetCreateMutable(0x0, 0x0, &stack[-128]);
rbx = _NSKeyValuePropertyForIsaAndKeyPathInner.llvm.13863498383568664478(r15, r14, rax);
CFRelease(rax);
if (0x0 == 0x0) {
if (**___stack_chk_guard == **___stack_chk_guard) {
rax = rbx;
}
else {
rax = __stack_chk_fail();
}
}
else {
rax = objc_exception_rethrow();
}
}
return rax;
}
int __NSKeyValueContainerClassForIsa(int arg0, int arg1, int arg2) {
rdi = arg0;
if (*0x4c29c0 != rdi) {
r15 = rdi;
r14 = __NSKVONotifyingOriginalClassForIsa(rdi);
if (*0x4c29d0 != 0x0) {
//獲取原來的類
rax = CFDictionaryGetValue(*0x4c29d0, r14);
rbx = rax;
if (rax == 0x0) {
//創建中間類
rax = [NSKeyValueContainerClass alloc];
rax = [rax initWithOriginalClass:r14];
rbx = rax;
CFDictionarySetValue(*0x4c29d0, r14, rax);
[rbx release];
}
}
else {
*0x4c29d0 = CFDictionaryCreateMutable(0x0, 0x0, 0x0, *_kCFTypeDictionaryValueCallBacks);
rax = [NSKeyValueContainerClass alloc];
rax = [rax initWithOriginalClass:r14];
rbx = rax;
CFDictionarySetValue(*0x4c29d0, r14, rax);
[rbx release];
}
*0x4c29c0 = r15;
*0x4c29c8 = rbx;
}
else {
rbx = *0x4c29c8;
}
rax = rbx;
return rax;
}
/* @class NSKeyValueContainerClass */
-(void *)initWithOriginalClass:(void *)arg2 {
r14 = arg2;
var_38 = self;
*(&var_38 + 0x8) = *0x4ace20;
rax = [[&var_38 super] init];
rbx = rax;
if (rax != 0x0) {
*(rbx + 0x8) = r14;
//observationInfo這個屬性中存儲有屬性的監聽者,監聽的keyPath,通知者,等
//是公開api
//調用方法id a = self.p.observationInfo;
*(rbx + 0x10) = class_getMethodImplementation(r14, sel_registerName("observationInfo"));
r14 = *(rbx + 0x8);
rax = sel_registerName("setObservationInfo:");
rax = class_getInstanceMethod(r14, rax);
*(rbx + 0x18) = method_getImplementation(rax);
method_getArgumentType(rax, 0x2, &var_21, 0x1);
if (var_21 == 0x40) {
*(int8_t *)(rbx + 0x20) = 0x1;
}
}
if (**___stack_chk_guard == **___stack_chk_guard) {
rax = rbx;
}
else {
rax = __stack_chk_fail();
}
return rax;
}
通過打印observationInfo這個屬性 可以得到:監聽者,監聽的keyPath,通知者,
同一屬性給同一個觀察者添加兩次就會出現兩個相同的。
查看setObservationInfo源碼
/* @class NSObject */
-(void)setObservationInfo:(void *)arg2 {
r14 = arg2;
rbx = self;
rdi = *_NSKeyValueObservationInfoPerObject.llvm.18255262684423441536;
if (rdi == 0x0) {
rax = CFDictionaryCreateMutable(0x0, 0x0, 0x0, 0x0);
rdi = rax;
*_NSKeyValueObservationInfoPerObject.llvm.18255262684423441536 = rax;
}
rsi = !rbx;
if (r14 != 0x0) {
CFDictionarySetValue(rdi, rsi, r14);
}
else {
CFDictionaryRemoveValue(rdi, rsi);
}
return;
}
鳴謝