------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! ———
/*****************************************
* 今天对 “KVO(键值监听)”进行学习.收获如下:
*
* KVO的用处⭐️:例如,如果程序的需求是:在数据模型组件的状态数据发生改变时,视图组件能动态地更新自己。
* 方案1⃣️:让数据模型组件持有一个视图组件的引用,当数据发生改变时,数据模型组件回调视图组件的方法使其得到更新。
* 不足:很显然,视图组件应该依赖于数据组件。如果用这种方法,就会形成一种双向依赖,这是很糟糕的设计。
*
* 方案2⃣️:利用ios提供的消息中心(NSNotificationCenter)来解决,让数据组件作消息生产者,视图组建作消息消费者。
* 每当数据组件的状态数据发生改变时,数据组件向消息中心发送消息,该消息会激发视图组件来消费该消息。
* 不足:虽然避免了双向依赖,但数据组件和视图组件都要与ios的消息中心耦合,每次更新都需要向ios消息中心发送消息
*
*****************************************
*
* KVO⭐️: KVO机制由NSKeyValueObserving协议提供支持,而NSObject遵守了该协议(即所有类都遵守了该协议)。
*
* 1.常用方法如下:
* __
* | 1⃣️ addObserver: forKeyPath: options: context: 注册一个监听器用于监听指定的key路径
* | 2⃣️ removeObserver: forKeyPath: 为key路径删除制定的监视器
* < 3⃣️ removeObserver: forKeyPath: context: 为key路径删除指定的监视器,指示多了一个context参数
* | 4⃣️ observeValueForKeyPath: ofObject: change: context:
* |__ 监听器对象需重写该方法,来触发监听器。
*
* 2.KVO整体来说步骤非常简单:1⃣️为被监听的对象注册监听器(通常是数据模型组件)。 2⃣️重写监听器触发方法(上述第4条)。
*
*
*******************************************/
代码实现:
#import <Foundation/Foundation.h>
/**************************************************************************************/ // LBXYItem类
@interface LBXYItem : NSObject //声明LBXYItem类
@property(nonatomic, copy) NSString* name;
@property(nonatomic, assign) int price;
@end
/********/
@implementation LBXYItem //实现LBXYItem类
@synthesize name;
@synthesize price;
@end
/**************************************************************************************/
/**************************************************************************************/ // LBXYItemView类
@interface LBXYItemView : NSObject //声明LBXYItemView类
@property(nonatomic, weak) LBXYItem* item;
- (void) showItemInfo;
@end
/*******/
@implementation LBXYItemView //实现LBXYItemView类
@synthesize item = _item;
- (void) showItemInfo
{
NSLog(@"item物品为:%@,物品价格为:%d\n\n", self.item.name, self.item.price);
//NSLog(@"\n");
}
//覆写setItem:方法
- (void) setItem : (LBXYItem *) item
{
_item = item;
//为item添加监听器,监听对象为自身,监听自身的name属性改变
[self.item addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
//为item添加监听器,监听item的price属性
[self.item addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew context:nil];
}
//覆写监听器触发方法
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"-------observeValueForKeyPath方法被调用---------------");
NSLog(@"被修改的keyPath为:%@",keyPath);
NSLog(@"被修改的对象为:%@",object);
NSLog(@"新修改的属性值为:%@",[change objectForKey:@"new"]);
NSLog(@"被修改的上下文为:%@\n\n",context);
}
-(void) dealloc
{
//删除监听器
[self.item removeObserver:self forKeyPath:@"name"];
[self.item removeObserver:self forKeyPath:@"price"];
}
@end
/**************************************************************************************/
int main(int argc, const char * argv[])
{
@autoreleasepool
{
LBXYItem* item = [[LBXYItem alloc] init];
item.name = @"初设name";
item.price = 1;
LBXYItemView* itemView = [[LBXYItemView alloc] init];
itemView.item = item;
[itemView showItemInfo];
//再次更改item对象的属性,将会激发监听器方法
item.name = @"更改name";
item.price = 2;
itemView.item.name = @"再次更改name";
itemView.item.price = 3;
}
return 0;
}<span style="color:#4bd157;">
</span>