键值观察之KVO——即观察者模式的应用

KVO的基本概念
1、基本概念:
Key Value Observing ,直译为:基于键值的观察者。它提供一种机制,当指定的对象的属性被修改后,则对象就会接收到通知。简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了。(常用于监听进度条的值)
与NSNotification不同,键-值 观察中并没有所谓的中心对象来为观察者提供变化通知。取而代之的,当有变化时,通知被直接发送至处于观察状态的对象。NSObject提供这种基础的 键-值 观察实现方法。
我们可以观察任意对象属性,包括简单属性,一对一或一对多关系。对多关系的观察者将会被被告知发生变化的类型-也就是任意发生变化的对象。
键-值 观察为所有对象提供自动观察兼容性。我们可以通过禁用自动观察通知并实现手动通知来筛选通知。
2、代理与观察者的区别就是:代理是一对一,观察者是一对多的。

就是说一个对象的代理只能是一个,就好比一次只能给一个人打电话一样,而观察者就好比是广播,所有人都会受到通知。代理只能实现一对一是无法实现一对多的。


新建工程:

创建一个孩子类:

编辑Child.h如下:

//
//  Child.h
//  KVOTest
//
//  Created by yanlu guo on 13-7-28.
//  Copyright (c) 2013年 河北科技大学. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Child : NSObject
{
    NSInteger happyVal;
}

@property(nonatomic,assign) NSInteger happyVal;

@end
编辑Child.m如下:

//
//  Child.m
//  KVOTest
//
//  Created by yanlu guo on 13-7-28.
//  Copyright (c) 2013年 河北科技大学. All rights reserved.
//

#import "Child.h"

@implementation Child

@synthesize happyVal;

// 可以发现孩子类中并没有护士的对象  但是护士仍然受到了通知
// 并不只是护士 ,而是所有的类的中都可以为孩子添加一个观察者
-(id)init{
    if(self = [super init]){
        self.happyVal = 100;
        [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerAction:) userInfo:nil repeats:YES];
    }
    return self;

}

-(void) timerAction:(NSTimer *) timer{
   self.happyVal--;  // 注意:使用点语法即 调用set方法才能触发监听操作
}

@end
新建护士类 当孩子快乐值减到一定程度时 观察者就会通知护士执行照顾孩子的操作

编辑Nurse.h如下:

//
//  Nurse.h
//  KVOTest
//
//  Created by yanlu guo on 13-7-28.
//  Copyright (c) 2013年 河北科技大学. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Child.h"

@interface Nurse : NSObject
{
    Child * child; 
}

@property(nonatomic,retain) Child * child;

-(id) initWithChild:(Child *) _child;
@end
编辑Nurse.m如下:

//
//  Nurse.m
//  KVOTest
//
//  Created by yanlu guo on 13-7-28.
//  Copyright (c) 2013年 河北科技大学. All rights reserved.
//

#import "Nurse.h"

@implementation Nurse
@synthesize child;

-(id) initWithChild:(Child *) _child{
    if(self = [super init]){
        child = [_child retain];
        // 使用KVO 为child添加一个观察者  用于监听happyVal是否被修改了
        
        // 把新旧值都传过来  self表示在当前类中执行监听方法
        // | 表示把新的值和旧的值(即监听的happyVal的新值和旧值都传过来)
        [child addObserver:self forKeyPath:@"happyVal" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:@"xxx"];
    }
    return self;
}

-(void) dealloc{
    [child removeObserver:self forKeyPath:@"happyVal"];
    [child release];
    [super dealloc];
}

// 一旦监听的happyVal的值被修改就会触发下面的方法
// 以下方法是NSObject的方法 触发监听后执行  与前面的  addObserver方法是配套使用的
-(void) observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary *)change 
                       context:(void *)context{
        NSNumber *happyValue = [change objectForKey:@"new"];
    NSInteger value = happyValue.integerValue;
    NSLog(@"快乐值是:%0.1f %%",value/100.0* 100);
    if (value< 80) {   // 如果小孩的欢乐值小于80  就会哭
        [self play];   // 观察者就会通知保姆照顾小孩
        [child setHappyVal:100];  // 孩子的欢乐值又重新变为100
    }

}

-(void)play
{
    NSLog(@"陪小孩玩");
}

@end


在main.m中编辑如下:

//
//  main.m
//  KVOTest
//
//  Created by yanlu guo on 13-7-28.
//  Copyright (c) 2013年 河北科技大学. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Child.h"
#import "Nurse.h"

int main (int argc, const char * argv[])
{

    @autoreleasepool {
        
        Child * child = [[Child alloc] init];
        [[Nurse alloc] initWithChild:child];
        [[NSRunLoop currentRunLoop] run];        
        
    }
    return 0;
}

运行结果如下:




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值