kvo的由来:在编程的过程中,我们经常需要判断,目标是否发生变化,以便即是得作出对应的处理。此时苹果公司就提供了一种策略,’即OC运行时’提供了’KVO’技术,其中’KVO’是基于’KVC’的,
KVO的实现:
1.注册观察者
2.观察者定义KVO回调
3.移除观察者
被观察的目标:
#import <Foundation/Foundation.h>
@interface Weather : NSObject
@property(nonatomic,assign)NSInteger PH25;
@end
创建一个座位观察者的类:
#import <Foundation/Foundation.h>
#import "Weather.h"
@interface Person : NSObject
@property(nonatomic,assign)Weather *weather;
@end
1.注册观察者person观察weather的PH2.5值
#import "ViewController.h"
#import "Person.h"
#import "Weather.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Weather *weather = [Weather new];
Person *person = [Person new];
person.weather= weather;
weather.PH25 = 15;
//1.注册观察者(此过程要谁是被观察者,谁是观察者,通过观察哪个路径的变化,要获取什么值)
[weather addObserver:person forKeyPath:@"PH25" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
weather.PH25 = 20;
}
2.在观察者的实现文件中,实现回调方法(必须);
//2.定义观察者的回调方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
NSLog(@"下面是我回调的值");
NSLog(@"ph2.5 = %@",change[NSKeyValueChangeNewKey]);
}
3.移除观察者:在观察者的实现稳健里面重写dealloc方法
//3.移除观察者
-(void)dealloc{
[self.weather removeObserver:self forKeyPath:@"PH25"];
NSLog(@"我已经移除");
}
以下是运行结果:
2015-12-24 18:03:01.606 kvo[1841:98182] 下面是我回调的值
2015-12-24 18:03:01.607 kvo[1841:98182] ph2.5 = 20
2015-12-24 18:03:01.607 kvo[1841:98182] 我已经移除
总结:KVO是基于KVC的,通过键值观察(注册观察者)目标的变化做出反应(回调方法)。
另:可以用时间戳来不断调用某一方法进行改变,KVO可以通过这个改变不断作处反应,
//此方法是设定隔多少时间运行后面的方法
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(change:) userInfo:nil repeats:YES];
//所以如果在主线程中可以不用写NSRunLoop做运行环境的语句,但是如果在非主线程中就要将NSTimer加入到该线程的NSRunLoop中,并启动NSRunLoop才可以,
// [[NSRunLoop currentRunLoop]run];//此语句是为NSTimer添加运行环境
// NSLog(@"main RunLoop = %@",[NSRunLoop mainRunLoop]);//查看是否已经有此环境
}
-(void)change:(NSTimer *)timr
{
NSUInteger _curHP = [[hero1 valueForKey:@"_HP" ]integerValue];
_curHP -= 50;
if (_curHP <= 0) {
[hero1 setValue:[NSNumber numberWithInteger:_curHP] forKey:@"_HP"];
[timr invalidate];//退出时间戳运行的方法
}else {
//更新减一次后的血量
[hero1 setValue:[NSNumber numberWithInteger:_curHP] forKey:@"_HP"];
}
}