#import
<Foundation/Foundation.h>
#import "FKItem.h"
@interface FKItemView : NSObject
@property ( nonatomic , weak ) FKItem * item;
- ( void ) showItemInfo;
@end
@implementation FKItemView
- ( void ) showItemInfo
{
NSLog ( @"item 物品名为 %@ ,物品价格为: %d" , self . item . name , self . item . price );
}
- ( void ) setItem:( FKItem *) item
{
self -> _item = item;
[ self . item addObserver : self forKeyPath : @"name"
options : NSKeyValueObservingOptionNew context : nil ];
[ 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 ( @" 被修改的上下文为 :%@" , context);
}
- ( void ) dealloc
{
[ self . item removeObserver : self forKeyPath : @"name" ]; // 删除监听器
[ self . item removeObserver : self forKeyPath : @"price" ]; // 删除监听器
}
@end
int main()
{
FKItem * item = [[ FKItem alloc ] init ];
item. name = @" 衬衫 " ;
#import "FKItem.h"
@interface FKItemView : NSObject
@property ( nonatomic , weak ) FKItem * item;
- ( void ) showItemInfo;
@end
@implementation FKItemView
- ( void ) showItemInfo
{
NSLog ( @"item 物品名为 %@ ,物品价格为: %d" , self . item . name , self . item . price );
}
- ( void ) setItem:( FKItem *) item
{
self -> _item = item;
[ self . item addObserver : self forKeyPath : @"name"
options : NSKeyValueObservingOptionNew context : nil ];
[ 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 ( @" 被修改的上下文为 :%@" , context);
}
- ( void ) dealloc
{
[ self . item removeObserver : self forKeyPath : @"name" ]; // 删除监听器
[ self . item removeObserver : self forKeyPath : @"price" ]; // 删除监听器
}
@end
int main()
{
FKItem * item = [[ FKItem alloc ] init ];
item. name = @" 衬衫 " ;
item.price = 99;
FKItemView* itemView = [[FKItemView alloc] init];
itemView.
item
= item;
[itemView showItemInfo ];
item. name = @" 短袖 " ;
item. price = 69 ;
[itemView showItemInfo ];
item. name = @" 短袖 " ;
item. price = 69 ;
}
一、编写本节代码的具体步骤:
1.可仿照第二章001节的代码编写步骤,可以把类的接口文件,类的实现文件写在main.m文件中。
2.本节代码要与
第二章
022节中的FKItem.m文件共同编译运行。
二、本节代码涉及到的知识点:
1.在iOS界面编程中,我们需要在数据模型组件的数据发生改变时,视图组件能动态地更新自己,
及时显示更新之后的数据。
2.KVO(键值监听)是上述问题的一个优秀的解决方案。当数据模型组件的key路径对应的属性值发生改变时,
作为监听器的视图组件将会被激发,激发时就会调用observeValueForKeyPath:ofObject:change:context:方法。
3.使用KVO
(键值监听)
的步骤非常简单:
①为被监听的对象(通常是数据模型组件)注册监听器
②重写监听器的observeValueForKeyPath:ofObject:change:context:方法。
4.
KVO
(键值监听)的常用方法如下:
addObserver:forKeyPath:option:context: // 注册一个监听器用于监听指定的key路径
removeObserver:forKeyPath: // 为key路径删除指定的监听器
removeObserver:forKeyPath:context: // 为key路径删除指定的监听器,只是多了一个context参数
5.本节代码定义了一个FKItemView类,该类模拟一个视图组件。该视图组件中包含了一个FKItem类型的item属性,
该属性代表数据模型组件。而showItemInfo方法用于显示该数据模型组件的状态。