首页 > 代码库 > KVO机制

KVO机制

#import <Foundation/Foundation.h>
#import "Person.h"
#import "BankAccount.h"

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

//    实例化一个人, 表示是这个名字叫wangdelong的人, 准备在银行开户
    
    Person *person = [[Person alloc] init];
    
    person.name=@"wangdelong";

    
//    实例化一个银行账户对象, 表示这个zhangsan在银行的开户信息
    
    BankAccount *account = [[BankAccount alloc]initWithPerson:person];
    
    
//    第二个参数:这里表达的意思, 当accountBlance发生变化的时候(注意必须以kvc或者是set方法改变才行),要通知监听者新的数据, 和老的数据
    [account addObserver:person forKeyPath:@"accountBlance" options:NSKeyValueObservingOptionPrior | NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    
//    改变银行存款
    [account changAccountBlance:200];
    
//    监听开始,有数据变化就执行,没有数据变化就等待,
    [[NSRunLoop currentRunLoop] run];
    
    
}

************************************************

#import <Foundation/Foundation.h>

@interface Person : NSObject

//每个人都有一个名字
@property (nonatomic,retain) NSString *name;

@end

************************************************

#import "Person.h"

@implementation Person

//系统自带的方法------专门用于监听
//第一个参数:是监听的keyPath.
//第二个参数:临听的是哪个对象,在我们模拟的例子里, 指的Account
//第三个参数:监听的值发生的变化,会存放到这个字典里。
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"%@",change);
    
    
// 因为在监听的时候, 监听的是accountBlance值变化前后的值, 所以这里可以根据NSKeyValueChangeNewKey取出新值
//   变化后的值——————————表示变化的钱数————————花的钱
    float newBlance = [[change valueForKeyPath:NSKeyValueChangeNewKey] floatValue];
//   变化前的值——————————表示原先的钱数————————以前的钱
    float oldBlance = [[change valueForKeyPath:NSKeyValueChangeOldKey] floatValue];
    
    NSLog(@"%f",newBlance);
    NSLog(@"%f",oldBlance);
    NSLog(@"尊敬的客户, 你当前消费了%f元, 余额是%f元",newBlance,oldBlance-newBlance);
    
}

************************************************

#import <Foundation/Foundation.h>


// 骗编译器,有这个类
@class Person;
@interface BankAccount : NSObject


@property (nonatomic,retain)Person *person;

//账户余额
@property (nonatomic,assign)float accountBlance;


//由于每一个银行账号,都必须与一个人关联, 所以在初始化的时候, 我们要指定一个人
-(id)initWithPerson:(Person *)person;

//每一个银行,都有权来根据实际情况, 修改账户里的钱,所以需要抽像出这个方法
-(void)changAccountBlance:(float)newValue;

@end

************************************************

#import "BankAccount.h"

@implementation BankAccount



-(id)initWithPerson:(Person *)person
{
    self = [super init];
    if (self) {
        _person = person;
        _accountBlance = 1000;
    }
    return self;
}

-(void)changAccountBlance:(float)newValue
{
    //    对于KVO来说, 最重要的, 必须采用set 或者是kvc的方法来修改属性的值, 否则不会引起通知事件发生。

#warning  注意
//    这里用下划线是不可以的,对于kvo而言,必须采用set方法或者是kvc的方法来修改属性的值,但是这里用下划线相当于直接赋值,所以是不可以这样做的,最起码要用self的方式
//        _accountBlance = newValue;
    
    self.accountBlance = newValue;
    
    //    self.accountBlance = newValue; //采用的set 方法来修改属性的值, 所以可以引起通知事件。
    //    以下, 是采用了KVC的机制, 所以也可以引起通知事件
    //    [self setValue:[NSNumber numberWithFloat:newValue] forKey:@"accountBlance"];
    
    //    self->_accountBlance = newValue; 采用指针的方法来修改属性, 实际上相当于直接访问的属性值, 所以,也不会引起通知事件的发生。
}
@end
************************************************