KVO

参考
https://www.jianshu.com/p/4748ef75126a
https://blog.csdn.net/wzzvictory/article/details/9674431?utm_source=tuicool

@interface Person : NSObject

@property (nonatomic, assign) int age;

@end
_person = [[Person alloc] init];

    /**
     *  添加观察者
     *
     *  @param observer 观察者
     *  @param keyPath  被观察的属性名称
     *  @param options  观察属性的新值、旧值等的一些配置(枚举值,可以根据需要设置,例如这里可以使用两项)
     *  @param context  上下文,可以为nil。
     */
[_person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
/**
 *  KVO回调方法
 *
 *  @param keyPath 被修改的属性
 *  @param object  被修改的属性所属对象
 *  @param change  属性改变情况(新旧值)
 *  @param context context传过来的值
 */
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"%@对象的%@属性改变了:%@", object, keyPath, change);
 
    //当有多个被观察者的时候就要写判断
    if([keyPath isEqualToString:@"age"] && object == _person)
    {
        NSLog(@"\noldnum:%@ newnum:%@", [change valueForKey:@"old"], [change valueForKey:@"new"]);
    }
}
/**
 *  移除观察者
 */
- (void)dealloc
{
    [_person removeObserver:self forKeyPath:@"age"];
}

其他

@interface Person : NSObject
{
@public
    int _age;
}

@property (nonatomic, assign) int age;

@end

@implementation Person

- (void)setAge:(int)age
{
    _age = age;
    
    NSLog(@"%s",__func__);
}

@end
    static int i = 1;
    
    //setter方法赋值
    //_person.age = i++;
    
    //KVC赋值
    //[_person setValue:@(i++) forKey:@"age"];
    
    //成员变量赋值 不会调用监听
    _person->_age = i++;
    NSLog(@"%d", _person->_age);

其他

KVO_第1张图片
最后的调用栈
- (void)setName:(NSString *)name
{
    _name = [name copy];
    
    NSLog(@"%s", __FUNCTION__);
}

- (void)willChangeValueForKey:(NSString *)key
{
    [super willChangeValueForKey:key];
    
    NSLog(@"%s", __FUNCTION__);
    
    NSLog(@"self->isa:%@", object_getClass(self));
    NSLog(@"self class:%@", [self class]);
}

- (void)didChangeValueForKey:(NSString *)key
{
    [super didChangeValueForKey:key];
    
    NSLog(@"%s", __FUNCTION__);
    
    NSLog(@"self->isa:%@", object_getClass(self));
    NSLog(@"self class:%@", [self class]);
}
2018-09-03 17:38:34.600836+0800 KVO[359:124313] -[Person willChangeValueForKey:]
2018-09-03 17:38:42.592813+0800 KVO[359:124313] self->isa:NSKVONotifying_Person
2018-09-03 17:38:43.336736+0800 KVO[359:124313] self class:Person
2018-09-03 17:40:28.206718+0800 KVO[359:124313] -[Person didChangeValueForKey:]
2018-09-03 17:40:28.206908+0800 KVO[359:124313] self->isa:NSKVONotifying_Person
2018-09-03 17:40:28.207017+0800 KVO[359:124313] self class:Person

NSKVONotifying_Person 是子类

NSKVONotifying_Person
- (void)setName:(NSString *)newName
{
    [self willChangeValueForKey:@"name"];    // KVO在调用存取方法之前总调用
    [super setValue:newName forKey:@"name"]; // 调用父类的存取方法
    [self didChangeValueForKey:@"name"];     // KVO在调用存取方法之后总调用
}

include
self->isa
object_getClass
target build setting direct usage of 'isa' set NO

你可能感兴趣的:(KVO)