Key-Value Coding Programming Guide 官方文檔第二部分第6節 2018.9.20 第一次修正html
##訪問器搜索方式app
NSObject默認實現NSKeyValueCoding協議提供的基於鍵的訪問器,使用一組明肯定義的規則來調用對象的基礎屬性。這些協議方法使用鍵參數在其本身的對象實例中搜索訪問器,實例變量以及遵循某些命名約定的相關方法。儘管您不多修改此默認搜索, 但瞭解它的工做方式會有所幫助,對於跟蹤鍵值編碼對象的行爲,也可使您本身的對象兼容。ide
注意 本節中的描述使用
<key>
或<Key>
做爲鍵字符串的佔位符,該鍵字符串在一個鍵值編碼協議方法中做爲參數出現,而後該方法將該鍵字符串用做間接方法調用或變量名稱查找的一部分。映射的屬性名稱遵循佔位符大小寫的狀況。例如,對於getter<key>
和is<KEY >
,名爲hidden
的屬性映射爲hidden
和isHidden
.。性能
valueForKey:
的默認實現,給定一個key
參數做爲輸入,在接收valueForKey:
調用的類實例中操做,執行如下過程。ui
1.搜索實例與名稱,按照該順序,搜索找到的名稱爲get<Key>
、<key>
、is<Key>
或<key>
的第一個訪問器方法。若是找到,調用它並繼續到步驟5。不然請繼續執行下一步。編碼
2.若是找不到簡單取值方法, 則在實例中搜索其方法名形如 countOf<Key>
和objectIn<Key>AtIndex:
(至關於NSArray
類中定義的基本方法)和<key>AtIndexes
:(至關於NSArray
類中的objectsAtIndexes:
方法)的方法。設計
若是第一個方法和後邊兩個方法中的至少一個方法被實現了, 則建立一個可以響應全部NSArray
方法並返回該方法的集合代理對象。不然, 繼續執行步驟3。代理
代理對象隨後將它接收的任何NSArray消息轉換爲countOf <Key>
,objectIn <Key> AtIndex:
和<key> AtIndexes:
的消息,並將其發送給建立它的鍵值編碼兼容對象。若是原始對象還實現了一個名爲get <Key>:range:
的可選方法,則代理對象也會在適當時使用該方法。實際上,與符合鍵值編碼的對象一塊兒工做的代理對象容許底層屬性的行爲就像它是同樣NSArray
,即便它不是。指針
3.若是沒有找到簡單的訪問器方法或數組訪問方法組,請查找名爲countOf <Key>
,enumeratorOf <Key>
和memberOf <Key>:
的方法的三個方法(對應於NSSet
類定義的原始方法)。
若是找到全部三個方法,請建立一個響應全部NSSet
方法並返回該方法的集合代理對象。 不然,請繼續執行步驟4。
這個代理對象隨後將它接收的任何NSSet
消息轉換爲count Of <Key>
,enumeration of <Key>
和member Of <Key>:
消息到建立它的對象。實際上,與符合鍵值編碼的對象一塊兒工做的代理對象容許底層屬性的行爲就像它是同樣NSSet
,即便它不是。
4.若是找不到簡單訪問器方法或集合訪問方法組, 而且消息接收者的類方法accessInstanceVariablesDirectly
返回YES, 則系統按如下順序搜索名爲:_<key>
、 _is<Key>
、 <key>
或is<Key>
的實例變量。若是找到, 則直接獲取實例變量的值, 而後繼續執行步驟5。不然, 繼續跳轉到步驟6。
5.若是獲取到的屬性值是對象指針,即獲取的是對象, 則直接將對象返回。
若是獲取到的屬性值是NSNumber支持的數據類型, 則將其存儲在NSNumber實例並返回。 若是獲取到的屬性值不是 NSNumber 支持的類型, 則轉換爲NSValue對象, 而後返回。
6.若是上述全部方法都沒有執行,則調用valueForUndefinedKey:
。 默認狀況下,這會引起異常,但NSObject的子類能夠經過重載並根據特定key作一些特殊處理。
setValue:forKey:
的默認實現, 給定key
和value
參數做爲輸入, 在接收調用的對象內嘗試將名爲key的屬性設置爲value(或者, 對於非對象屬性, 則爲unwarp value, 詳見Representing Non-Object Values), 使用如下過程:
1.按照順序查找第一個名爲set<Key>:
或_set<Key>
的方法。若是找到, 傳入輸入值 (或根據須要展開值) 調用它, 而後完成。
2.若是找不到簡單訪問器, 而且類方法accessInstanceVariablesDirectly
返回YES, 則按如下順序查找實例變量: _<key>
、 _is<Key>
、<key>
、is<Key>
。若是找到, 則直接使用輸入值 (或展開值) 設置變量並完成。
3.若是找不到以上方法或實例變量, 則調用setValue:forUndefinedKey:
。默認狀況下,這會引起異常,但NSObject
的子類能夠經過重載並根據特定key作一些特殊處理。
mutableArrayValueForKey:
的默認實現,給定一個key
參數做爲輸入,使用如下過程爲接收訪問者調用的對象內的一個名爲key
的屬性返回一個可變代理數組:
1.查找一對方法, 名爲insertObject:in <Key> AtIndex:
和removeObjectFrom <Key> AtIndex:
的方法(分別對應於NSMutableArray
原始方法insertObject:atIndex:
和removeObjectAtIndex:
) ,或者名稱相似於insert <Key>:atIndexes:
和remove <Key> AtIndexes:
(對應於NSMutableArrayinsertObjects:atIndexes:
和removeObjectsAtIndexes:
方法)。
若是對象至少實現一個插入方法和至少一個刪除方法,則返回一個響應NSMutableArray
消息的代理對象,方法是發送insertObject:in <Key> AtIndex:
,removeObjectFrom <Key> AtIndex:
,insert <Key>:atIndexes:
,和remove <Key> AtIndexes:
消息到mutableArrayValueForKey:
的原始接收者。
當接收mutableArrayValueForKey:
消息的對象也實現了一個可選的替換對象方法,其名稱如replaceObjectIn <Key> AtIndex:withObject:
或replace <Key> AtIndexes:with <Key>:
,代理對象在適合最佳性能時會自動調用該可選方法。
2.若是對象沒有可變數組方法,則查找名稱與模式set <Key>:
匹配的訪問器方法。 在這種狀況下,經過向mutableArrayValueForKey:
的原始接收者發出set <Key>:
消息,返回響應NSMutableArray消息的代理對象。
注意: 此步驟中描述的機制比上一步的效率要低得多, 由於它可能涉及重複建立新的集合對象, 而不是修改現有的。所以, 在設計本身的鍵值編碼兼容對象時, 一般應避免這種狀況。
3.若是既沒有找到可變數組方法,也沒有找到訪問器,而且接收者的類對accessInstanceVariablesDirectly
響應'YES,則按照順序搜索名爲
_ 或
`的實例變量。
若是找到這樣的實例變量,則返回一個代理對象,該對象將它接收的每一個NSMutableArray
消息轉發給實例變量的值,該值一般是NSMutableArray
的實例或其子類之一。
4.若是全部其餘方法都失敗了,只要收到NSMutableArray
消息,就返回一個可變集合代理對象,該對象向mutableArrayValueForKey:
消息的原始接收者發出setValue:forUndefinedKey:
消息。
setValue:forUndefinedKey:的默認實現會拋出NSUndefinedKeyException異常, 但子類可能會重寫此行爲。
mutableOrderedSetValueForKey的默認實現:將相同的簡單訪問器方法和有序集訪問器方法識別爲valueForKey :
(請參閱 Default Search Pattern for the Basic Getter ),並遵循相同的直接訪問實例變量策略,但始終返回可變集合代理對象 valueForKey:
返回的不可變集合。 此外,它還執行如下操做:
1.搜索名稱相似於如下形式的方法: insertObject:in <Key> AtIndex:
和removeObjectFrom <Key> AtIndex:
(對應於NSMutableOrderedSet
類定義的兩個最原始方法),以及insert <Key>: atIndexes:
和remove <Key> AtIndexes:
(對應於insertObjects:atIndexes:
和removeObjectsAtIndexes:
)。
若是找到至少一個insert方法和至少一個remove方法,返回的代理對象每次接收到 NSMutableOrderedSet的消息後, 會經過如下組合方法給mutableOrderedSetValueForKey
的原始對象 發送消息: mutableOrderedSetValueForKey:
insertObject:in<Key>AtIndex:
, removeObjectFrom <Key> AtIndex :
, insert <Key>:atIndexes:
remove<Key>AtIndexes:
代理對象還使用方法名爲 replaceObjectIn <Key> AtIndex:withObject:
的方法,或replace<Key>AtIndexes:with<Key>:
,當這些方法存在於原始對象中時。
2.若是找不到可變的set方法,請搜索名爲set <Key>:
的訪問器方法。 在這種狀況下,返回的代理對象每次收到NSMutableOrderedSet
消息時都會向mutableOrderedSetValueForKey:
的原始接收者發送一個set <Key>:
消息。
注意 此步驟中描述的機制比前一步驟的效率低得多,由於它可能涉及重複建立新的集合對象而不是修改現有的集合對象。 所以,在設計本身的符合鍵值編碼的對象時,一般應該避免使用它。
3.若是找不到可變集消息和訪問器,而且接收者的accessInstanceVariablesDirectly
類方法返回YES
,則按順序搜索名稱如_ <key>
或<key>
的實例變量。 若是找到這樣的實例變量,則返回的代理對象將它接收的任何NSMutableOrderedSet
消息轉發給實例變量的值,該值一般是NSMutableOrderedSet
或其子類之一的實例。
4.若是全部其餘方法都失敗了,那麼只要收到一個可變的set消息,返回的代理對象就會向mutableOrderedSetValueForKey:
的原始接收者發送一個setValue:forUndefinedKey:
消息。
setValue:forUndefinedKey:
的默認實現引起了一個NSUndefinedKeyException
,可是對象可能會覆蓋此行爲。
mutableSetValueForKey:
的默認實現,給定一個key
參數做爲輸入,使用如下過程爲接收訪問者調用的對象內的一個名爲key
的數組屬性返回一個可變代理集:
1.搜索方法名稱爲add<Key>Object:
和 remove <Key> Object
的方法:(分別對應於NSMutableSet
原始方法addObject:
和removeObject:
)以及add<Key>:
和remove<Key>:
(對應於NSMutableSet
方法unionSet:
和minusSet:
)。若是找到至少一個添加方法和至少一個刪除方法,則返回一個NSMutableSet代理對象,該代理對象發送add <Key> Object:
,remove <Key> Object:
,add <Key>:
的某種組合, 和remove <Key>:
對於它收到的每一個NSMutableSet
消息的mutableSetValueForKey:
的原始接收者的消息。
代理對象還使用名稱爲「cross:」或「set:」的方法來提升性能(若是可用的話)。
2.若是mutableSetValueForKey:
調用的接收者是託管對象,則搜索模式不會像非託管對象那樣繼續。 有關更多信息,請參閱「Core Data Programming Guide 」中的託管對象訪問器方法。
3.若是找不到可變集合方法,而且對象不是託管對象,則搜索名爲set <Key>:
的訪問器方法。 若是找到這樣的方法,則返回的代理對象將set <Key>:
消息發送給它接收的每一個NSMutableSet消息的mutableSetValueForKey:
的原始接收者。
注意 此步驟中描述的機制的效率遠低於第一步的機制,由於它可能涉及重複建立新的集合對象而不是修改現有的集合對象。 所以,在設計本身的符合鍵值編碼的對象時,一般應該避免使用它。
4.若是找不到可變的set方法和accessor方法,而且accessInstanceVariablesDirectly
類方法返回YES
,則按照順序搜索名爲_ <key>
或<key>
的實例變量。 若是找到這樣的實例變量,則代理對象將它接收的每一個NSMutableSet
消息轉發給實例變量的值,該值一般是NSMutableSet
的實例或其子類之一。
5.若是全部其餘方法都失敗了,返回的代理對象經過向mutableSetValueForKey:'的原始接收者發送
setValue:forUndefinedKey:消息來響應它收到的任何
NSMutableSet`消息。
因爲筆者水平有限,文中若是有錯誤的地方,或者有更好的方法,還望大神指出。 附上本文的全部 demo 下載連接,【GitHub】。 若是你看完後以爲對你有所幫助,還望在 GitHub 上點個 star。贈人玫瑰,手有餘香。