反編譯Foundation框架,通過蘋果源碼初探KVO

從添加觀察者開始

[_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;
}

 

 

 

 

鳴謝

KVO引發出來的血案

iOS開發-黑科技防止多次添加刪除KVO出現的問題

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章