版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2017.09.14 |
前言
KVO
具有更強大的功能吸占,是蘋果給我們的一個回調(diào)機制,在某個對象注冊監(jiān)聽者后凿宾,在被監(jiān)聽的對象發(fā)生改變時矾屯,對象會發(fā)送一個通知給監(jiān)聽者,以便監(jiān)聽者執(zhí)行回調(diào)操作初厚。接下來幾篇就詳細的解析一下KVO件蚕。感興趣的可以看上面幾篇。
1. KVO解析(一) —— 基本了解
2. KVO解析(二) —— 一個簡單的KVO實現(xiàn)
KVO合規(guī)性
考慮到對于指定屬性KVO的合規(guī)性产禾,一個類必須滿足下面關系:
改類對于指定的屬性必須是 key-value coding compliant 排作,這在 Ensuring KVC Compliance中已經(jīng)指明。
該類發(fā)送對于屬性的
KVO change
通知亚情。依賴的key被合適的注冊(可以參考Registering Dependent Keys)
Automatic Change Notification
NSObject提供了一個自動鍵值改變通知的基本實現(xiàn)妄痪,自動鍵值更改通知通知觀察者使用鍵值兼容的訪問器進行的更改以及鍵值編碼方法。 由例如mutableArrayValueForKey
返回的集合代理對象也支持自動通知楞件。
下面例子展示的是name屬性更改是觀察者收到的通知衫生。
//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];
Manual Change Notification
有的時候,你也許想要控制通知的處理過程土浸,例如罪针,針對應用程序特定原因而不必要的觸發(fā)通知,或將一些更改分組到單個通知中黄伊。 手動更改通知提供了這樣做的手段泪酱。
手動和自動通知不是互斥的。 除了自動的通知之外,您還可以自由發(fā)布手動通知西篓。 更通常地愈腾,您可能希望完全控制特定屬性的通知。 在這種情況下岂津,您將重寫NSObjec的automaticNotificationsObserversForKey
的實現(xiàn)。 對于要排除其自動通知的屬性悦即,automaticNotificationsObserversForKey
的子類實現(xiàn)應該返回NO吮成。一個子類實現(xiàn)應該為任何無法識別的key調(diào)用super超類。 下面代碼中的示例啟用了對balance
屬性的手動通知辜梳,允許超類確定所有其他鍵的通知粱甫。
// Example implementation of automaticallyNotifiesObserversForKey:
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey
{
BOOL automatic = NO;
if ([theKey isEqualToString:@"balance"]) {
automatic = NO;
}
else {
automatic = [super automaticallyNotifiesObserversForKey:theKey];
}
return automatic;
}
為了實現(xiàn)手動觀察通知,在值改變之前作瞄,你需要調(diào)用方法 willChangeValueForKey:茶宵,并在值改變之后調(diào)用方法 didChangeValueForKey:,下面的例子實現(xiàn)了對balance
屬性的手動通知宗挥。
- (void)setBalance:(double)theBalance
{
[self willChangeValueForKey:@"balance"];
_balance = theBalance;
[self didChangeValueForKey:@"balance"];
}
您可以通過首先檢查值是否已更改來最小化發(fā)送不必要的通知乌庶。 下面的例子展示的是balance
的值改變時,并且在已經(jīng)改變的時候提供通知平挑。
// Testing the value for change before providing notification
- (void)setBalance:(double)theBalance
{
if (theBalance != _balance) {
[self willChangeValueForKey:@"balance"];
_balance = theBalance;
[self didChangeValueForKey:@"balance"];
}
}
如果單個操作導致多個鍵更改薄货,則必須嵌套更改通知而晒,如下所示。
- (void)setBalance:(double)theBalance
{
[self willChangeValueForKey:@"balance"];
[self willChangeValueForKey:@"itemChanged"];
_balance = theBalance;
_itemChanged = _itemChanged+1;
[self didChangeValueForKey:@"itemChanged"];
[self didChangeValueForKey:@"balance"];
}
在有序的多關系的情況下透敌,您不僅必須指定更改的密鑰,還必須指定所涉及的對象的更改類型和索引踢械。 更改類型是NSKeyValueChange
酗电,它指定NSKeyValueChangeInsertion
,NSKeyValueChangeRemoval
或NSKeyValueChangeReplacement
内列。 受影響的對象的索引作為NSIndexSet
對象傳遞撵术。
下面中的代碼片段演示了如何在多對象關系事務中包裝對象的刪除。
// 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"];
}
后記
未完德绿,待續(xù)~~~