kvo作用
KVO俗稱鍵值監聽,它提供一種機制,當指定的對象的屬性被修改後,則對象就會接收到通知。就是每次指定的被觀察的對象的屬性被修改後,KVO就會自動通知想要的觀察者。
使用步驟:
步驟一
給對象添加監聽者
首先創建一個person類
@interface Person :NSObject
@property(nonatomic,copy) NSString *name;
@end
//在viewcontroller擴展中添加一個屬性
@property(nonatomic,strong) Person *person;
//並給該屬性初始化對象,並給屬性添加kvo監聽
self.person = [Person new];
[self.person addObserver:self forKeyPath:@"name"options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
具體參數說明:
- observer:觀察者
- forkeyPath參數是一個鍵值對中的鍵,唯一標示符綁定值。
- options:
NSKeyValueObservingOptionNew:change字典包括改變後的值
NSKeyValueObservingOptionOld: change字典包括改變前的值
NSKeyValueObservingOptionInitial: 註冊後立刻觸發KVO通知
NSKeyValueObservingOptionPrior: 值改變前是否也要通知
- context:上下文,這個會傳遞到訂閱者的函數中,用來區分消息,所以應當是不同的。
步驟二
如果修改了person的name的值就會觸發下面方法
//需要在這裏實現監聽後要做的操作
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
步驟三
刪除指定Key路徑的監聽器:
在- (void)dealloc;方法中移除監聽
- (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context
kvo原理
主要用到了運行時(runtime)
當某個類的對象第一次被觀察時,會通過運行時動態地創建對應於該類的一個派生類,在這個派生類中系統會重寫父類中被觀察屬性的setter方法。然後根據options中的值來確定觸發哪些方法,下面會觸發改變前和改變後的方法。
-(void)setName:(NSString *)name{
[self willChangeValueForKey:@"name"];//會在值即將發生變化時發送通知
_name = name;
[self didChangeVauleForKey:@"name"]; //會在值已經發生變化時發送通知
}
automaticallyNotifiesObserversForKey該方法用於是否自動觸發kvo,返回no要手動觸發,
+(BOOL)automaticallyNotifiesObserversForKey:(NSString *)key{
if([key isEqualToString:@"name"]){
return NO;
}
return [super automaticallyNotifiesObserversForKey:key];
}
應用
商城購物車中都有一個全選按鈕,如果每個商品都一一勾選後,那麼全選按鈕就會被自動選中。如果其中一個商品沒有選中,然後全選按鈕不會被選中。
這裏需要監聽加入購物車數組對象。
@interface ViewController ()
//下單數據源
@property(nonatomic,strong) NSMutableArray *pendingDataSource;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//監聽pendingDataSource對象是否發生變化
[self addObserver:self forKeyPath:@"pendingDataSource" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}
-(void)addAction{
[[self mutableArrayValueForKey:@"pendingDataSource"] addObject:person];
}