kvo,与观察者模式类似,通过给指定的对象设置观察者,来检测对象的变化,当指定的对象的属性被修改后,用于作为观察者的对象会接收到通知。简单的说就是每次指定的被观察的对象的属性被修改后,kvo就会自动通知相应的观察者。系统框架已经支持kvo,所以在开发过程中可以直接使用,非常方便。
| 一、kvo的使用步骤 |
1、注册,指定被观察者的属性
2、实现回调方法
3、移除观察
| 二、通过现实中的小例子介绍一下kvo的用法 |
我有一张银行卡,只要卡内的金额发生的改变,银行就会发短信给我提示,下面通过代码使用kvo来模拟一下这个过程
先创建一个Card银行卡类,卡里有money金额的属性,在初始化这张卡的时候,给卡里金额设置一个初值1000,然后每隔1秒钟模拟消费10元,代码如下:
Card.h
// Card.h // KVO // // Created by jerei on 15-6-5. // Copyright (c) 2015年 jerehedu. All rights reserved. // #import <Foundation/Foundation.h> @interface Card : NSObject @property (nonatomic, assign) float money; @end
Card.m
// Card.m
// KVO
//
// Created by jerei on 15-6-5.
// Copyright (c) 2015年 jerehedu. All rights reserved.
//
#import "Card.h"
@implementation Card
-(instancetype)init
{
if (self = [super init]) {
_money = 1000.0;
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(changeMoney) userInfo:nil repeats:YES];
}
return self;
}
//改变卡内金额
-(void)changeMoney
{
self.money -= 10;
}
@end
再创建一个People人类,在这个类中有姓名name和card银行卡两个属性。
People.h
// People.h // KVO // // Created by jerei on 15-6-5. // Copyright (c) 2015年 jerehedu. All rights reserved. // #import <Foundation/Foundation.h> @class Card; @interface People : NSObject @property (nonatomic, copy) NSString *name; @property (nonatomic, strong) Card *card; -(id)initWithName:(NSString *)name andCard:(Card *)card; @end
People.m
// People.m
// KVO
//
// Created by jerei on 15-6-5.
// Copyright (c) 2015年 jerehedu. All rights reserved.
//
#import "People.h"
#import "Card.h"
@implementation People
-(id)initWithName:(NSString *)name andCard:(Card *)card
{
if (self = [super init]) {
_name = name;
_card = card;
}
return self;
}
@end
创建好了两个类之后,在People类中通过kvo来监测银行卡中金额的变化
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
调用方法的是被监听的对象,参数分别为:
addObserver:观察者
forKeyPath:被监听的对象的属性,属性里面还有属性的,可以用点语法
options:想监听的对象是什么操作,比如初始化、有新的值
context:上下文,一般为nil,当KeyPath:相同时,可以用它来区分
因此,在People.m中需要添加的代码为:
-(id)initWithName:(NSString *)name andCard:(Card *)card
{
if (self = [super init]) {
_name = name;
_card = card;
//注册,添加观察者
[_card addObserver:self forKeyPath:@"money" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
}
return self;
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
observeValueForKeyPath:字符串,被监听的属性
ofObject:哪一个对象被监听
change:字典,包含了变化前和变化后的值
context:上下文
因此,在People.m中需要实现回调方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"回调方法 %@",change);
}
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
调用方法的是被监听的对象
removeObserver:观察者
forKeyPath:字符串
因此,在People.m中重写dealloc方法,实现移除监听者
-(void)dealloc
{
[_card removeObserver:self forKeyPath:@"money"];
}
例子中Card类中有一个changeMoney方法,在这个方法中修改了被监听属性的值,下面介绍4中方法给大家。
-(void)changeMoney
{
//不能直接改值!!!!
_money -= 10; //错误的
//1.点语法
self.money -= 10;
//2. set方法
float f = _money-10;
[self setMoney:f];
//3. kvc
[self setValue:@(f) forKey:@"money"];
//4.
[self willChangeValueForKey:@"money"];
_money -= 10;
[self didChangeValueForKey:@"money"];
}
原文:http://www.cnblogs.com/zyj442714794/p/4593807.html