ViewController.h
#import "ViewController.h"
#import "Hero.h"
#import "Observe.h"
@interface ViewController ()
{
Hero *hero;
Observe *observe;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//KVO
/*
KVO的由来:在编程的过程中,我们经常需要判断目标是否发生变化,以便及时的做出对应的处理。此时苹果公司就提供了一种策略,即'OC运行时'提供了'KVO'技术。其中'KVO'是基于'KVC'实现
KVO的实现:
1.注册成观察者
2.观察者定义KVO回调
3.移除观察者
*/
hero = [Hero new];
[hero setValue:@100 forKey:@"_HP"];
observe = [[Observe alloc]initWithHero:hero];
[hero setValue:@300 forKey:@"_HP"];
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(change:) userInfo:nil repeats:YES];
//所以如果在主线程中可以不用写NSRunLoop作运行环境的语句,但是如果在非主线程中就要将NSTimer加入到该线程的NSRunLoop中,并启动NSRunLoop才行。
[[NSRunLoop currentRunLoop] run];
//NSLog(@"main RunLoop = %@",[NSRunLoop mainRunLoop]);
}
-(void)change:(NSTimer *)timer
{
// NSLog(@"continue running");
NSUInteger _curHP = [[hero valueForKey:@"_HP"] integerValue];
_curHP -= 50;
if (_curHP <= 0)
{
[hero setValue:@0 forKey:@"_HP"];
[timer invalidate];
}
else
{
[hero setValue:[NSNumber numberWithInteger:_curHP] forKey:@"_HP"];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
Hero.h
#import <Foundation/Foundation.h>
@interface Hero : NSObject
{
NSUInteger _HP;
}
@end
Hero.m
#import "Hero.h"
@implementation Hero
@end
Observe.h
#import <Foundation/Foundation.h>
#import "Hero.h"
@interface Observe : NSObject
@property(nonatomic,retain)Hero *hero ;
-(id)initWithHero:(Hero *)hero ;
@end
Observe.m
#import "Observe.h"
@implementation Observe
-(id)initWithHero:(Hero *)hero
{
if (self = [super init])
{
self.hero = hero ;
//注册监听者
/*
P225
NSKeyValueObservingOptionNew
NSKeyValueObservingOptionOld
NSKeyValueObservingOptionInitial
NSKeyValueObservingOptionPrior
*/
[self.hero addObserver:self forKeyPath:@"_HP" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}
return self;
}
//定义KVO回调
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
NSLog(@"change = %@",change[NSKeyValueChangeNewKey]);
/*
change 是一个字典 包含的key有如下 P226
NSKeyValueChangeKindKey
NSKeyValueChangeNewKey //新值
NSKeyValueChangeOldKey //旧值
NSKeyValueChangeIndexesKey
NSKeyValueChangeNotificationIsPriorKey
*/
}
//移除监听者
-(void)dealloc
{
/*
NSObject类定义了一个方法叫做dealloc,当对象没有拥有者并且内存要被回收时,系统会自动调用dealloc方法。dealloc的责任是释放对象自己的内存,释放所有它控制的资源,包括释放所有实例变量的所有权。
*/
[self.hero removeObserver:self forKeyPath:@"_HP"];
NSLog(@"I am die");
}
@end
运行结果
2015-12-20 23:52:40.472 OC_08_02[2006:69166] change = 300
2015-12-20 23:52:41.474 OC_08_02[2006:69166] change = 250
2015-12-20 23:52:42.474 OC_08_02[2006:69166] change = 200
2015-12-20 23:52:43.474 OC_08_02[2006:69166] change = 150
2015-12-20 23:52:44.474 OC_08_02[2006:69166] change = 100
2015-12-20 23:52:45.474 OC_08_02[2006:69166] change = 50
2015-12-20 23:52:46.474 OC_08_02[2006:69166] change = 0