Objective-C KVC,KVO简单使用

🌰  :动画

首先建立一个YJCPerson类,该类有三个属性,分别是name,age和一个YJCDog,YJCDog有一个dogName属性atom

@interface YJCPerson : NSObject

+ (instancetype)personWithName:(NSString *)name age:(NSInteger)age dogName:(NSString *)dogName;
- (instancetype)initWithName:(NSString *)name age:(NSInteger)age dogName:(NSString *)dogName;

@end

#import "YJCPerson.h"
#import "YJCDog.h"

@interface YJCPerson ()

@property (nonatomic, copy)   NSString *name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, strong) YJCDog   *dog;

@end

@implementation YJCPerson

+ (instancetype)personWithName:(NSString *)name age:(NSInteger)age dogName:(NSString *)dogName{
    YJCPerson *person = [[self alloc]initWithName:name age:age dogName:dogName];return person;
}

- (instancetype)initWithName:(NSString *)name age:(NSInteger)age dogName:(NSString *)dogName{
    if (self = [self init]) {
        self.name = name;
        self.age  = age;
        self.dog.dogName = dogName;
    }
    return self;
}

- (instancetype)init{
    if (self = [super init]) {
        self.dog = [YJCDog new];
    }
    return self;
}

@end

对于一个类,最好有便利构造方式spa

在VC中对该类添加监看指针

#import "ViewController.h"
#import "YJCPerson.h"

@interface ViewController ()

@property (nonatomic, strong) YJCPerson *person;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
    [self.person addObserver:self forKeyPath:@"dog.dogName" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
    [self.person setValue:@"YJC" forKey:@"name"];//KVC的setValue:forKey:
    [self.person setValue:@"大黄" forKeyPath:@"dog.dogName"];//KVC的setValue:forKeyPath:
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context 
{
if ([keyPath isEqualToString:@"name"])
{
NSLog(
@"YJCPerson 更名了,%@-->%@",[change valueForKey:@"old"],[change valueForKey:@"new"]);
}
else if ([keyPath isEqualToString:@"dog.dogName"])
{
NSLog(
@"YJCPerson.dog 更名了,%@-->%@",[change valueForKey:@"old"],[change valueForKey:@"new"]);
}
}
- (YJCPerson *)person
{
return _person?:({
_person
= [[YJCPerson alloc]init];
[_person setValue:
@"name" forKey:@"name"];
[_person setValue:
@"dog" forKeyPath:@"dog.dogName"];
_person;
});
}
//若是添加了KVO,必定要记得释放
- (void)dealloc
{
[self removeObserver:self.person forKeyPath:
@"name"];
[self removeObserver:self.person forKeyPath:
@"dog.dogName"];
}

@end

KVC主要是经过键值路径得到相应的属性,而且能够得到私有属性code

那么它获取路径的顺序是什么呢server

- (NSString *)getName;对象

- (NSString *)name;blog

- (NSString *)isName;rem

首先会依次查找这三个方法,固然既然声明的是属性,那么系统就默认实现了getter方法,因此会在第一步就找到.get

那么若是这三个方法都没有找到呢

由于name是string类型的,不不太明显.若是是array类型的话,系统会继续找响应的方法

例如-(id)objectInNameAtIndex:(NSUInteger)index;

若是依然没有找到,那么系统就会找- (id)valueForUndefineKey:(NSString *)key;若是该方法内依然没有找到相关key,则会crash,因此咱们能够经过从新该方法来防止程序crash

现实中KVC主要作的工做是对一些系统类的私有属性的赋值,像设置占位字符颜色啦,动画的一些属性啦什么的

KVO   

KVO呢用法就是经过对某一实例的相关属性添加监看,系统会执行回调,切记添加了KVO必定要记得释放,写法呢大概就这个样子,示例而已

KVO的实现呢主要是该机制为被监控对象建立了一个分类NSKVONotifying_Class  Class就是被监看的实例所属类.而后该机制会重写该属性的setter方法,setter在调用原setter方法以前和以后,经过KVO机制通知全部监看对象

固然这些行为是隐藏的,系统会经过runtime建立该分类,并把被监看对象的isa指针指向该分类,既然isa指针指向了该分类,那么setter方法天然就是调用该分类里已经重写过的setter方法咯,重写的时候添加了willChange和didChange两个方法用来通知监看对象

还有一点:遵循KVO赋值的方式才会触发KVO,直接对实例变量赋值是不会触发KVO机制的

切记,添加了监看必定要移除监看

相关文章
相关标签/搜索