1.1 KVO的定義
KVO(Key-Value Observing)搪哪,俗稱鍵值監(jiān)聽。它提供一種機制狠半,當指定的對象的屬性被修改后噩死,則對象就會接受到通知颤难。簡單的說就是每次指定的被觀察的對象的屬性被修改后,KVO就會自動通知相應(yīng)的觀察者了已维。
1.2 KVO的使用
KVO的定義KVO是“觀察者”設(shè)計模式的一種應(yīng)用,利用它可以很容易實現(xiàn)視圖組件和數(shù)據(jù)模型的分離行嗤,當數(shù)據(jù)模型的屬性值改變之后作為監(jiān)聽器的視圖組件就會被激發(fā),激發(fā)時就會回調(diào)監(jiān)聽器自身垛耳。這種模式有利于兩個類間的解耦合栅屏,尤其是對于業(yè)務(wù)邏輯與視圖控制 這兩個功能的解耦合。和KVC類似,在ObjC中要實現(xiàn)KVO則必須實現(xiàn)NSKeyValueObServing協(xié)議堂鲜,但不用擔心,因為NSObject已經(jīng)實現(xiàn)了該協(xié)議栈雳,因此幾乎所有的ObjC對象都可以使用KVO.
1.3KVO常用的方法
1>注冊指定Key路徑的監(jiān)聽器
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
相關(guān)參數(shù):
observer:觀察者,也就是KVO通知的訂閱者。訂閱著必須實現(xiàn)
observeValueForKeyPath:ofObject:change:context:方法
keyPath:描述將要觀察的屬性缔莲,相對于被觀察者哥纫。
options:KVO的一些屬性配置;有四個選項痴奏。
options所包括的內(nèi)容:
NSKeyValueObservingOptionNew: change字典包括改變后的值
NSKeyValueObservingOptionOld: change字典包括改變前的值
NSKeyValueObservingOptionInitial:注冊后立刻觸發(fā)KVO通知
NSKeyValueObservingOptionPrior:值改變前是否也要通知(這個key決定了是否在改變前改變后通知兩次)
context: 上下文蛀骇,這個會傳遞到訂閱著的函數(shù)中,用來區(qū)分消息读拆,所以應(yīng)當是不同的擅憔。
注意:不要忘記解除注冊,否則會導(dǎo)致資源泄露
2>刪除指定Key路徑的監(jiān)聽器:
- (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context
3>回調(diào)監(jiān)聽
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
keyPath:被監(jiān)聽的keyPath , 用來區(qū)分不同的KVO監(jiān)聽檐晕。
object: 被觀察修改后的對象(可以通過object獲得修改后的值)
change:保存信息改變的字典(可能有舊的值暑诸,新的值等)
context:上下文,用來區(qū)分不同的KVO監(jiān)聽
KVO的使用步驟也比較簡單
1>注冊辟灰,指定被觀察者的屬性
2> 實現(xiàn)回調(diào)方法
3>移除觀察
1.4 KVO的使用場景
@interface StockData : NSObject {
NSString * stockName;
float price;
}
@end
@implementation StockData
@end
- (void)viewDidLoad
{
[super viewDidLoad];
stockForKVO = [[StockData alloc] init];
[stockForKVO setValue:@"searph" forKey:@"stockName"];
[stockForKVO setValue:@"10.0" forKey:@"price"];
[stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
myLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 30 )];
myLabel.textColor = [UIColor redColor];
myLabel.text = [stockForKVO valueForKey:@"price"];
[self.view addSubview:myLabel];
UIButton * b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
b.frame = CGRectMake(0, 0, 100, 30);
[b addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:b];
}
-(void) buttonAction
{
[stockForKVO setValue:@"20.0" forKey:@"price"];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if([keyPath isEqualToString:@"price"])
{
myLabel.text = [stockForKVO valueForKey:@"price"];
}
}
- (void)dealloc
{
[stockForKVO removeObserver:self forKeyPath:@"price"];
}