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機制的

切記,添加了監看必定要移除監看

相關文章
相關標籤/搜索