KVO 两种方式支持属性改变通知发送

Two techniques Ensuring the Changing Notification Emitted

官方文档

There are two techniques for ensuring the change notifications are emitted.

Automatic Change Notification

NSObject provides a basic implementation of automatic key-value change notification. Automatic key-value change notification informs observers of changes made using key-value compliant accessors, as well as the key-value coding methods. Automatic notification is also supported by the collection proxy objects returned by, for example, mutableArrayValueForKey:

NSObject 提供了当属性值发生改变时自动发送通知的机制。

那什么时候自动发送通知呢?

  • 使用遵守KVC的属性访问器
  • 使用 KVC 方法,如 setValue:forKey: or setValue:forKeyPath:
  • mutableArrayValueForKey: 返回的代理集合对象也支持自动发送通知。

Examples of method calls that cause KVO change notifications to be emitted

// Call the accessor method.
[account setName:@"Savings"];
 
// Use setValue:forKey:.
[account setValue:@"Savings" forKey:@"name"];
 
// Use a key path, where 'account' is a kvc-compliant property of 'document'.
[document setValue:@"Savings" forKeyPath:@"account.name"];
 
// Use mutableArrayValueForKey: to retrieve a relationship proxy object.
Transaction *newTransaction = <#Create a new transaction for the account#>;
NSMutableArray *transactions = [account mutableArrayValueForKey:@"transactions"];
[transactions addObject:newTransaction];

若不用 mutableArrayValueForKey: 返回的代理对象,addObject: 不会自动发送改变通知。

Manual Change Notification

背景:

In some cases, you may want control of the notification process, for example, to minimize triggering notifications that are unnecessary for application specific reasons, or to group a number of changes into a single notification. Manual change notification provides means to do this.

有的时候你想要控制通知的过程。

有的时候你想屏蔽一些没必要的通知,例如:当且仅当属性值不同时,才发送通知;观察者只注册一个 key,当一组 keys 发生变化时,通知注册了 key 的观察者,免去了需观察多个 key。

实现
  • 重写 NSObject 的 +automaticallyNotifiesObserversForKey:,对于不启用自动通知的 keys,返回 NO,对于不处理的 keys,调用 super。

    + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey {
    	BOOL automatic = NO;
        if ([theKey isEqualToString:@"balance"]) {
        	automatic = NO;
    	}
    	else {
        	automatic = [super automaticallyNotifiesObserversForKey:theKey];
    	}
    	return automatic;
    }
    
  • 手动调用 -willChangeValueForKey, -didChangeValueForKey: 触发通知

    - (void)setBalance:(double)theBalance {
        [self willChangeValueForKey:@"balance"];
    	_balance = theBalance;
    	[self didChangeValueForKey:@"balance"];
    }
    
  • to-many relationships 不仅仅要指定 key,还要指定改变的类型,改变元素的 indexes

    - (void)removeTransactionsAtIndexes:(NSIndexSet *)indexes {
        [self willChange:NSKeyValueChangeRemoval
        valuesAtIndexes:indexes forKey:@"transactions"];
    
    	// Remove the transaction objects at the specified indexes.
    
    	[self didChange:NSKeyValueChangeRemoval
        valuesAtIndexes:indexes forKey:@"transactions"];
    }
    
Manual Change Notification 优化点

You can minimize sending unnecessary notifications by first checking if the value has changed.

- (void)setBalance:(double)theBalance {
    if (theBalance != _balance) {
        [self willChangeValueForKey:@"balance"];
        _balance = theBalance;
        [self didChangeValueForKey:@"balance"];
    }
}

group a number of changes into a single notification

 (void)setBalance:(double)theBalance {
    [self willChangeValueForKey:@"balance"];
    [self willChangeValueForKey:@"itemChanged"];
    _balance = theBalance;
    _itemChanged = _itemChanged+1;
    [self didChangeValueForKey:@"itemChanged"];
    [self didChangeValueForKey:@"balance"];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值