KVO本质

2021-02-27  本文已影响0人  Berning
@interface NSPerson : NSObject

@property(nonatomic,assign)int  age;
@property(nonatomic,assign)double  height;

@end

@implentation NSPerson
- (void)setAge:(int)age
{
    _age = age;
}
@end


@interface ViewController ()
@property(nonatomic,strong)NSPerson *person;
@end

@ implentation viewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.person = [NSPerson new];
    self.person.age = 10;
    self.person.height = 180;
}
@end

本质

    IMP imp = [self.person methodForSelector:@selector(setAge:)];
    IMP imp2 = [person2 methodForSelector:@selector(setAge:)];
Printing description   of imp:
(IMP) imp = 0x00007fff258f10eb (Foundation`_NSSetIntValueAndNotify)
Printing description of imp2:
(IMP) imp2 = 0x00000001059716e0 (KVO`-[NSPerson setAge:] at NSPerson.h:15)
(lldb) 

//伪代码
@implentation NSKVONotifying_NSPerson
- (void)setAge:(int)age
{
    _NSSetIntValueAndNotify();
}

void  _NSSetIntValueAndNotify()
{
    [obj willChangeValueForKey:@"age"];
    [super setAge:age];
    [obj didChangeValueForKey:@"age"];
}

- (void) didChangeValueForKey:(NSString *)key
{
    [observer observeValueForKeyPath:@"age" ofObject:obj 
    change:@{old, new }  context:nil];
}

@end

子类

- (void)printMethodListForClass:(Class)cls
{
    unsigned int count;
    Method *methodList = class_copyMethodList(cls, &count);
    NSMutableString *methodString = [NSMutableString string];
    for (int i = 0; i < count; i++) {
        Method method = *(methodList + i);
        NSString *methodName = NSStringFromSelector(method_getName(method));
        [methodString appendFormat:@"%@,",methodName];
    }
    
    free(methodList);
    
    NSLog(@"%@",methodString);
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.person = [NSPerson new];
    self.person.age = 10;
    self.person.height = 180;

    NSPerson *person2 = [NSPerson new];
    person2.age = 20;
    person2.height = 175;
    
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;

    [self.person addObserver:self forKeyPath:@"age" options:options context:nil];
    [self.person addObserver:self forKeyPath:@"height" options:options context:nil];

    [self printMethodListForClass:object_getClass(self.person)];
    [self printMethodListForClass:object_getClass(person2)];
}

log

KVO[71463:2802731] setHeight:,setAge:,class,dealloc,_isKVOA,
KVO[71463:2802731] height,setHeight:,age,setAge:,

NSKVONotifying_NSPerson生成了下面方法

- (Class)class
{
    return [NSPerson class];
}
- (BOOL) _isKVOA
{
    return YES;
}

手动触发

    [self.person willChangeValueForKey:@"age"];
    [self.person didChangeValueForKey:@"age"];
上一篇 下一篇

猜你喜欢

热点阅读