KVO简介:
NSKeyValuesObserving(KVO)非正式协议定义了一种机制,允许一个对象被通知:另外某个对象的某个属性值被改变了。
你可以『监听』任何对象的属性,包括简单类型的属性。一对一,或者一对多。一对多的监听被通知到是什么类型发生变化,已及是哪个对象引起。
NSObject提供了一个NSKeyValueObserving协议的实现,它提供了一种能够自动监听到所有对象的能力。你能关闭自动观察通知并使用协议中的方法手动实现通知。
The NSKeyValueObserving (KVO) informal protocol defines a mechanism that allows objects to be notified of changes to the specified properties of other objects.
You can observe any object properties including simple attributes, to-one relationships, and to-many relationships. Observers of to-many relationships are informed of the type of change made — as well as which objects are involved in the change.
NSObject provides an implementation of the NSKeyValueObserving protocol that provides an automatic observing capability for all objects. You can further refine notifications by disabling automatic observer notifications and implementing manual notifications using the methods in this protocol.
栗子代码:
#pragma mark Person.h
@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) int age;
@end
#pragma mark Person.m
@implementation Person
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
NSLog(@"keyPath = %@, change = %@, context = %s", keyPath, change, (char *)context);
}
@end
#pragma mark Bank.h
@interface Bank : NSObject
@property (strong, nonatomic) NSString * accountBalance;
@end
#pragma mark main.m
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *xiao=[Person new];
Bank *bank=[Bank new];
[bank addObserver:xiao forKeyPath:@"accountBalance" options:NSKeyValueObservingOptionNew context:"1"];
[bank addObserver:xiao forKeyPath:@"accountBalance" options:NSKeyValueObservingOptionNew context:"2"];
[bank addObserver:xiao forKeyPath:@"accountBalance" options:NSKeyValueObservingOptionNew context:"3"];
[bank addObserver:xiao forKeyPath:@"accountBalance" options:NSKeyValueObservingOptionNew context:"4"];
[bank addObserver:xiao forKeyPath:@"accountBalance" options:NSKeyValueObservingOptionNew context:"5"];
bank.accountBalance=@"1 Billion";
[bank removeObserver:xiao forKeyPath:@"accountBalance"];
[bank removeObserver:xiao forKeyPath:@"accountBalance"];
[bank removeObserver:xiao forKeyPath:@"accountBalance"];
[bank removeObserver:xiao forKeyPath:@"accountBalance"];
[bank removeObserver:xiao forKeyPath:@"accountBalance"];
}
return 0;
}
输出:
2015-09-07 22:42:16.244 runtime_test[37288:14256239] keyPath = accountBalance, change = {
kind = 1;
new = "1 Billion";
}, context = 5
2015-09-07 22:42:16.245 runtime_test[37288:14256239] keyPath = accountBalance, change = {
kind = 1;
new = "1 Billion";
}, context = 4
2015-09-07 22:42:16.245 runtime_test[37288:14256239] keyPath = accountBalance, change = {
kind = 1;
new = "1 Billion";
}, context = 3
2015-09-07 22:42:16.245 runtime_test[37288:14256239] keyPath = accountBalance, change = {
kind = 1;
new = "1 Billion";
}, context = 2
2015-09-07 22:42:16.245 runtime_test[37288:14256239] keyPath = accountBalance, change = {
kind = 1;
new = "1 Billion";
}, context = 1
说明:
1. 重复添加的通知,依然会被发送和处理。
2. 对象被dealloc必须移除所有观察者,一个都不能漏,否则会报错:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x100109040 of class Bank was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x100109cc0>
3. 被添加为观察者的类必须实现-
(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context方法来响应keyPath的变化。
否者会报错:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '<Person: 0x100111e10>: An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
Key path: accountBalance
Observed object: <Bank: 0x100111fe0>
网友评论