iOS KVO 实现分析

来源:互联网 发布:电话名单软件 编辑:程序博客网 时间:2024/06/05 15:32

KVO提供了一种方法,当某个属性改变时,相应的对象会被通知。

概述

1、通过runtime实现,当观察某个对象时,runtime会创建一个新的子对象。在这个新对象中,它重写了所有被观察的key,然后将object的isa指向新class(这个指针告诉OC运行时某个对象到底是哪种类型的对象)。因此这个添加观察者的对象就无声无息间变成了新的子类的实例。

2、当出发setKey方法时通知会发出。由于新子类这个方法被重写了,并且在内部添加了发送通知的机制。

3、苹果公司不希望将这个实现暴露在外面。于是重写了-class方法。这样依旧返回原先的class!如果不仔细看的话,是否被加入观察者的对象没什么区别。

代码

////  main.m//  KVOTest////  Created by dujia on 16/2/4.//  Copyright © 2016年 杜甲. All rights reserved.//#import <UIKit/UIKit.h>#import "AppDelegate.h"#import <objc/runtime.h>@interface KVOTest1 : NSObject@property (nonatomic , assign) int a;@property (nonatomic , assign) int b;@property (nonatomic , assign) int c;@end@implementation KVOTest1@endstatic NSArray *ClassMethodNames(Class c){    NSMutableArray *array = [NSMutableArray array];        unsigned int methodCount = 0;    Method *methodList = class_copyMethodList(c, &methodCount);    unsigned int i;    for (i = 0; i < methodCount; i++) {        [array addObject:NSStringFromSelector(method_getName(methodList[i]))];    }    free(methodList);    return array;}static void PrintDescription(NSString *name, NSObject * obj){    NSString *str = [NSString stringWithFormat:                     @"%@: %@\n\tNSObject class %s\n\tlibobjc class %s\n\timplements methods <%@>",                     name,                     obj,                     class_getName([obj class]),                     class_getName(object_getClass(obj)),                     [ClassMethodNames(object_getClass(obj)) componentsJoinedByString:@", "]];    printf("%s\n", [str UTF8String]);}int main(int argc, char * argv[]) {        KVOTest1 *a = [[KVOTest1 alloc] init];    KVOTest1 *b = [[KVOTest1 alloc] init];    KVOTest1 *c = [[KVOTest1 alloc] init];           [c addObserver:c forKeyPath:@"c" options:0 context:NULL];     [b addObserver:b forKeyPath:@"b" options:0 context:NULL];    PrintDescription(@"a", a);    PrintDescription(@"b", b);    PrintDescription(@"c", c);        printf("Using NSObject methods, normal setB: is %p, overridden setB: is %p\n",           [a methodForSelector:@selector(setB:)],           [b methodForSelector:@selector(setB:)]);    printf("Using libobjc functions, normal setB: is %p, overridden setB: is %p\n",           method_getImplementation(class_getInstanceMethod(object_getClass(a), @selector(setB:))),           method_getImplementation(class_getInstanceMethod(object_getClass(b), @selector(setB:))));        @autoreleasepool {        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));    }}


运行结果:

a: <KVOTest1: 0x7f8b69f003f0>NSObject class KVOTest1libobjc class KVOTest1implements methods <a, setA:, b, setB:, c, setC:>b: <KVOTest1: 0x7f8b69f00460>NSObject class KVOTest1libobjc class NSKVONotifying_KVOTest1implements methods <setB:, setC:, class, dealloc, _isKVOA>c: <KVOTest1: 0x7f8b69f00480>NSObject class KVOTest1libobjc class NSKVONotifying_KVOTest1implements methods <setB:, setC:, class, dealloc, _isKVOA>Using NSObject methods, normal setB: is 0x10f4ff3b0, overridden setB: is 0x10f62ac6bUsing libobjc functions, normal setB: is 0x10f4ff3b0, overridden setB: is 0x10f62ac6b

没有加入观察者的A 输出:  libobjc class KVOTest1



代码下载 :http://download.csdn.net/detail/qqmcy/9427645

0 0
原创粉丝点击