objective c设计模式--KVO

来源:互联网 发布:js模块化框架 编辑:程序博客网 时间:2024/05/22 09:05
KVO
KVO的介绍
通常用于多个对象之间的通信,在一个对象中感知另一个对象的属性的变化。
建立连接,注册监听对象:
- (void) addObserver:(NSObject *) forKeyPath:(NSString *) options:(NSKeyValueObservingOptions) context:(void *);
回调函数:
}-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context ;
例子:一个客户监听银行账户余额

Person.h

#import <Foundation/Foundation.h> 

#import "BankCount.h" 

@interface Person : NSObject {

    BankCount *count;

 } //打开监听银行账号的能力

- (void) registerAsObsertver;

 - (void) unregisterAsObsertver;

 -(id)init;

 -(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context ; @end


Person.m

#import <Foundation/Foundation.h>

 #import "Person2.h"

 @implementation Person

 -(id)init {

    self = [super init];

    if (self){ 

       count =[[BankCount alloc] init];

    }

    return self;

}

 - (void) dealloc{

    count = nil;

    [super dealloc];

 }

 //OpeningBalance指向自己的指针

static void* OpeningBalance = (void *)&OpeningBalance;

 -(void) registerAsObsertver//监听银行账号的变化过程 

{

    [count addObserver:self forKeyPath:@"openingBalance" options: NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld context:OpeningBalance];    

//如果要监听多个对象可以添加如下代码

    //[count2 addObserver:self forKeyPath:@"openingBalance" options: NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld context:OpeningBalance];

    //给银行账号添加一个监听者 self,监听openingBalance的变化

    //只要openingBalance有变化(openingBalance有新的值),self就会知道

}

-(void) unregisterAsObsertver{

    //selfcount中解除监听的@"openingBalance"能力

    [count removeObserver:self forKeyPath:@"openingBalance"];

}

 //这个方法就是监听的回调函数

//就是说count里面的openingBalance只要有变化就会调用下面这个方法

//keyPath表示之前监听的key就是openingBalance

 // object表示count

 //change是一个字典,里面包含一个新,旧的值

//context是私有变量OpeningBalance 

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

NSLog(@"KeyPath %@,object %@,change %@",keyPath,object,change);

        if(context == OpeningBalance)

        //if ([keyPath isEqualToString:@"openingBalance"])

       {        

NSString *v =[change objectForKey:NSKeyValueChangeNewKey];

        NSLog(@"v is %@",v);

       }else{

        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];

       }

}

@end


BankCount.h

#import <Foundation/Foundation.h> 

@interface BankCount:NSObject{

    float _openingBalance; 

}

 @property (nonatomic, assign) float openingBalance;//表示银行账号的余额 @end


BankCount.m

#import <Foundation/Foundation.h>

#import "BankCount.h" 

@implementation BankCount 

@synthesize openingBalance = _openingBalance; 

- (instancetype)init {

    self = [super init];

    if (self) {

        [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(countUpdate:) userInfo:nil repeats:YES];         }    

    return self; 

-(void) countUpdate:(id)arg {

    float f = self.openingBalance;

    f =arc4random()%100;

    //有四种写法

    //1.

    self.openingBalance = f;

    //2.

    //[self setOpeningBalance:f];

    //3.KVC写法

    //[self setValue:[NSNumber numberWithFloat:f] forKey:@"openingBalance"];

    //4.

    //[self willChangeValueForKey:@"openingBalance"];

    //_openingBalance = f 

   //[self didChangeValueForKey:@"openingBalance"];

    //_openingBalance = f;这种方法不可以使用 

}

@end


mian.m
#import <Foundation/Foundation.h>

#import "Person2.h"

#import "BankCount.h" 

int main () {

    @autoreleasepool {


    Person *p = [[Person alloc] init];

    [p registerAsObsertver];

    [[NSRunLoop currentRunLoop] run]; 

    }

    return 0;

}

0 0
原创粉丝点击