OC_10_KVO

接着上一个内容,咱们来讲讲KVO(Key-Value Observing)
键值观察KVO是基于键值编码KVC的一种技术,利用键值观察可以注册成为一个对象的观察者,在该对象的某个属性变化时收到通知。要使用键值观察,被观察对象必须编写符合KVC标准的存取方法。

设计模式 – 观察者模式
设计模式是用来解决某一特定问题

观察者模式
◎什么是观察者模式?
在工程中,一些类去观察‘A’类,当‘A’类发生变化时,这些类就会收到消息,做出相应反应。
◎什么时候使用观察者模式?
当一个类需要发送消息给多个类的时候,就用观察者模式。
◎观察者模式的作用?
一对多的消息发送。
◎在OC中如何实现观察者模式?
OC中观察者模式的设计基础 KVC/KVO

KVO的由来:
在编程的过程中,我们经常需要判断目标是否发生变化,以便及时的做出对应的处理。此时苹果公司就提供了一种策略,即‘OC运行时’提供了‘KVO’技术。其中‘KVO’是基于’KVC‘实现。

KVO的实现:
1.注册成为观察者
2.观察者定义KVO回调
3.移除观察者

创建工程,创建一个Observer观察者和Hero英雄类:
这里写图片描述
我们的目的就是为了创建一个观察者来观察英雄的血量,然后让英雄自残,输出扣除的血量过程直至死亡。
好,咱进入到Observer.h文件:

#import "Hero.h"

@interface Observer : NSObject

@property (nonatomic,strong)Hero *hero;

-(id)initWithHero:(Hero *)hero;

@end

作为观察者,英雄作为被观察者,就需要将英雄的属性给到观察者,所以需导入头文件,以及@property一个英雄,下面那个就是个便利初始化函数嘛~
我们去Observer.m实现一下:

-(id)initWithHero:(Hero *)hero{

    if (self = [super init]) {

        self.hero = hero;
        //1.如何注册成为观察者
        /*
         第一个参数:观察者,通常为self
         第二个参数:键路径参数,要观察的键路径
         第三个参数:标识KVO希望变化如何传递给观察者,这些值可以使用‘|’进行多选
         第四个参数:上下文内存区,通常为nil
         */
        [self.hero addObserver:self forKeyPath:@"_HP" options:NSKeyValueObservingOptionNew context:nil];

    }
    return self;    
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{

    //2.如何定义观察者KVO的回调
    /*

     *///OldKey这条可省略,我只是试试输出两个
    NSLog(@"%@,%@",[change objectForKey:NSKeyValueChangeNewKey],[change objectForKey:NSKeyValueChangeOldKey]);

}
//3.移除观察者
-(void)dealloc{

    NSLog(@"你挂了");
    /*
     移除的观察者对象
     观察的键路径

     */
     [self.hero removeObserver:self forKeyPath:@"_HP"];    
}

去到英雄的接口文件,实现文件空着就好。英雄就是定义一个血量罢了:NSUInteger _HP;
OK,去到ViewController.m文件,看看下面的代码:

#import "Hero.h"
#import "Observer.h"
@interface ViewController ()
{
    Hero *_hero;//变成全局变量,这个之所以要定义成全局变量是因为英雄在计数器中要得到使用
    Observer *_observer; //定义全局变量,若不定义为全局变量,对象移除执行dealloc,不再执行计数器了。
}
@end
- (void)viewDidLoad {
    [super viewDidLoad];
    Hero *hero = [Hero new];//创建英雄对象
    //利用KVC给英雄血量赋值
    [hero setValue:@100 forKey:@"_HP"];
    //创建观察者对象
    Observer *observer = [[Observer alloc]initWithHero:hero];
    //再给英雄血量赋值,值都是随便赋值就行
    [hero setValue:@88 forKey:@"_HP"];
    //启动计数器,实现每1s扣血的功能
    [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(Time:) userInfo:nil repeats:YES];

    _hero = hero;//将局部变量赋给全局变量
    _observer = observer;//同上
}
-(void)Time:(NSTimer *)time{
    //定义当前血量,对HP进行拆包
   NSInteger _curHP = [[_hero valueForKey:@"_HP"]integerValue];
    _curHP -= 8;//让他每秒扣8滴血
    if (_curHP <=0) {
//        NSLog(@"英雄已死,有事烧纸");
        [_hero setValue:@0 forKey:@"_HP"];
        NSLog(@"英雄已死,有事烧纸");
        [time invalidate];//关闭计数器
    }else{

        [_hero setValue:@(_curHP) forKey:@"_HP"];//输出当前血量

    }
}

让我们看下运行结果:
这里写图片描述
这里之所以有个null,是因为我多输出一个,将其删掉即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值