In order to be considered KVO-compliant for a specific property, a class must ensure the following:
- The class must be key-value coding compliant for the property, as specified in Ensuring KVC Compliance.
KVO supports the same data types as KVC, including Objective-C objects and the scalars and structures listed in Scalar and Structure Support.- The class emits KVO change notifications for the property.
- Dependent keys are registered appropriately (see Registering Dependent Keys).
為了使特定屬性符合kVO標(biāo)準(zhǔn)缓溅,類必須確定以下幾點(diǎn):
- 類的屬性必須遵從KVC,如 Ensuring KVC Compliance中所述语稠。
KVO支持與KVC相同的數(shù)據(jù)類型耸袜,包括OC對(duì)象和標(biāo)量和結(jié)構(gòu)體支持中列舉的標(biāo)量和結(jié)構(gòu)體楼镐。 - 類會(huì)為屬性發(fā)出KVO變化通知馆截。
- 依賴的key path都被正確注冊(cè)(參考 Registering Dependent Keys)抖锥。
There are two techniques for ensuring the change notifications are emitted. Automatic support is provided by
NSObject
and is by default available for all properties of a class that are key-value coding compliant. Typically, if you follow standard Cocoa coding and naming conventions, you can use automatic change notifications—you don’t have to write any additional code.
有兩種技術(shù)可以確保發(fā)出變化通知宵喂。自動(dòng)支持是由NSObject
提供的糠赦,并且對(duì)所有遵從KVC的屬性都是默認(rèn)可用的。通常锅棕,如果你遵從標(biāo)準(zhǔn)的Cocoa編碼和命名約定拙泽,就可以使用自動(dòng)變化通知,不用寫額外的代碼裸燎。
Manual change notification provides additional control over when notifications are emitted, and requires additional coding. You can control automatic notifications for properties of your subclass by implementing the class method automaticallyNotifiesObserversForKey:.
手動(dòng)更改通知提供了對(duì)何時(shí)發(fā)出通知的額外控制顾瞻,需要額外的編碼。你可以通過實(shí)現(xiàn)方法automaticallyNotifiesObserversForKey:來控制子類屬性的自動(dòng)通知德绿。
自動(dòng)變化通知
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
提供了自動(dòng)鍵-值改變通知的基本實(shí)現(xiàn)荷荤。自動(dòng)鍵值改變通知通過使用鍵值兼容訪問器來通知觀察者所做的改變,以及KVC方法移稳。返回的集合代理對(duì)象也支持自動(dòng)通知蕴纳,例如mutableArrayValueForKey:
.
The examples shown in Listing 1 result in any observers of the property
name
to be notified of the change.
Listing 1的示例會(huì)導(dǎo)致屬性name
的任何的觀察者都會(huì)收到改變的通知
Listing 1 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];
手動(dòng)改變通知
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.
在一些情況中,你可能想要控制通知的過程秒裕,例如袱蚓,最小化因應(yīng)用程序特定的原因不必要的觸發(fā)通知,或者將多個(gè)更改分組到單個(gè)通知中几蜻。手動(dòng)改變通知提供了實(shí)現(xiàn)這個(gè)的方法喇潘。
Manual and automatic notifications are not mutually exclusive. You are free to issue manual notifications in addition to the automatic ones already in place. More typically, you may want to completely take control of the notifications for a particular property. In this case, you override the
NSObject
implementation ofautomaticallyNotifiesObserversForKey:
. For properties whose automatic notifications you want to preclude, the subclass implementation ofautomaticallyNotifiesObserversForKey:
should returnNO
. A subclass implementation should invoke super for any unrecognized keys. The example in Listing 2 enables manual notification for thebalance
property, allowing the superclass to determine the notification for all other keys.
手動(dòng)和自動(dòng)通知不是互斥的。 除了現(xiàn)有的自動(dòng)通知之外梭稚,您還可以自由發(fā)出手動(dòng)通知颖低。 更典型的是,您可能希望完全控制特定屬性的通知弧烤。 在這種情況下忱屑,您覆蓋automaticNotifiesObserversForKey:
的NSObject
實(shí)現(xiàn)。 對(duì)于要排除自動(dòng)通知的屬性暇昂,automaticNotifiesObserversForKey:
的子類實(shí)現(xiàn)應(yīng)返回NO
莺戒。 子類實(shí)現(xiàn)應(yīng)該為任何無法識(shí)別的鍵調(diào)用super。 Listing 2中的示例啟用了balance
屬性的手動(dòng)通知急波,允許超類確定所有其他鍵的通知从铲。
Listing 2 Example implementation of automaticallyNotifiesObserversForKey:
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey {
BOOL automatic = NO;
if ([theKey isEqualToString:@"balance"]) {
automatic = NO;
}
else {
automatic = [super automaticallyNotifiesObserversForKey:theKey];
}
return automatic;
}
To implement manual observer notification, you invoke willChangeValueForKey: before changing the value, and didChangeValueForKey: after changing the value. The example in Listing 3 implements manual notifications for the
balance
property.
為了實(shí)現(xiàn)手動(dòng)通知,在改變值之前調(diào)用 willChangeValueForKey:澄暮,在改變值之后調(diào)用 didChangeValueForKey:名段。Listing 3中的示例實(shí)現(xiàn)了balance
屬性的手動(dòng)通知阱扬。
Listing 3 Example accessor method implementing manual notification
- (void)setBalance:(double)theBalance {
[self willChangeValueForKey:@"balance"];
_balance = theBalance;
[self didChangeValueForKey:@"balance"];
}
You can minimize sending unnecessary notifications by first checking if the value has changed. The example in Listing 4 tests the value of
balance
and only provides the notification if it has changed.
你可以通過首先檢測值是否發(fā)生改變來最小化發(fā)送不必要的通知。Listing 4中的示例測試了balance
的值并且只有在它改變時(shí)才提供通知伸辟。
Listing 4 Testing the value for change before providing notification
- (void)setBalance:(double)theBalance {
if (theBalance != _balance) {
[self willChangeValueForKey:@"balance"];
_balance = theBalance;
[self didChangeValueForKey:@"balance"];
}
}
If a single operation causes multiple keys to change you must nest the change notifications as shown in Listing 5.
如果單個(gè)操作導(dǎo)致多個(gè)鍵發(fā)生了改變麻惶,你必須按照Listing 5所示嵌套變化通知。
Listing 5 Nesting change notifications for multiple keys
- (void)setBalance:(double)theBalance {
[self willChangeValueForKey:@"balance"];
[self willChangeValueForKey:@"itemChanged"];
_balance = theBalance;
_itemChanged = _itemChanged+1;
[self didChangeValueForKey:@"itemChanged"];
[self didChangeValueForKey:@"balance"];
}
In the case of an ordered to-many relationship, you must specify not only the key that changed, but also the type of change and the indexes of the objects involved. The type of change is an NSKeyValueChange that specifies
NSKeyValueChangeInsertion
,NSKeyValueChangeRemoval
, orNSKeyValueChangeReplacement
. The indexes of the affected objects are passed as an NSIndexSet object.
在有序的多對(duì)多關(guān)系情況下信夫,你必須指定更改的鍵和變化的類型以及相關(guān)對(duì)象的索引窃蹋。變化的類型是一個(gè) NSKeyValueChange類型,指定了NSKeyValueChangeInsertion
, NSKeyValueChangeRemoval
, 或 NSKeyValueChangeReplacement
忙迁。受影響的對(duì)象的索引作為一個(gè)NSIndexSet 對(duì)象被傳遞脐彩。
The code fragment in Listing 6 demonstrates how to wrap a deletion of objects in the to-many relationship
transactions
.
Listing 6中的代碼片段演示了如何在多對(duì)多關(guān)系事務(wù)中包裝一個(gè)刪除事件。
Listing 6 Implementation of manual observer notification in a to-many relationship
- (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"];
}