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{
//self从count中解除监听的@"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;
}