2010-02-19 75 views
16

我試圖理解Cocoa的Key-Value Coding(KVC)機制好一點。我讀過蘋果公司的Key-Value Programming Guide,但我仍然對某些KVC方法如何搜索密鑰感到困惑。特別是,mutableArrayValueForKey:什麼是mutableArrayValueForKey的KVC搜索模式?

下面我將解釋我如何理解valueForKey: KVC「getters」的工作。然後我會回到我關於mutableArrayValueForKey的問題。


有七種不同的 「吸氣劑」 KVC方法:

- (id)valueForKey:(NSString *)key; 
- (id)valueForKeyPath:(NSString *)keyPath; 
- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys; 
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key; 
- (NSMutableArray *)mutableArrayValueForKeyPath:(NSString *)keyPath; 
- (NSMutableSet *)mutableSetValueForKey:(NSString *)key; 
- (NSMutableSet *)mutableSetValueForKeyPath:(NSString *)keyPath; 

當一個屬性內的值搜索(命名爲的myKey),蘋果的文檔指出valueForKey:搜索這樣的:

  1. 試圖-getMyKey-myKey-isMyKey(在接收機內部的順序)
  2. 如果沒有找到,它會嘗試這些命令,對許多幹將(NSArray中):

    // Required: 
    - (NSUInteger)countOfMyKey; 
    
    // Requires At Least One: 
    - (id)objectInMyKeyAtIndex:(NSUInteger)index; 
    - (NSArray *)myKeyAtIndexes:(NSIndexSet *)indexes; 
    
    // Optional (improves performance): 
    - (void)getMyKey:(KeyClass **)buffer range:(NSRange)inRange; 
    
  3. 接下來,它會嘗試這些無序的,對許多幹將(NSSet中) :

    - (NSUInteger)countOfMyKey; 
    - (NSEnumerator *)enumeratorOfMyKey; 
    - (KeyClass *)memberOfMyKey:(KeyClass *)anObject; 
    
  4. 接着,它試圖直接訪問實例變量,假設YESaccessInstanceVariablesDirectly返回,在該順序:_myKey_isMyKeymyKeyisMyKey

  5. 最後,它放棄並調用接收類的- (id)valueForUndefinedKey:(NSString *)key方法。通常在這裏提出錯誤。


我的問題是,什麼是mutableArrayValueForKey搜索順序模式:?

Apple's docs state this

訪問器搜索模式的有序 集合

爲 mutableArrayValueForKey的默認搜索模式:作爲 如下:

接收器的類中搜索 對名稱與 模式匹配的方法-insertObject:inAtIndex: 和-removeObjectFromAtIndex: (對應於的NSMutableArray 原始的方法 insertObject:atIndex:和 removeObjectAtIndex:分別地),或 方法的圖案匹配 -insert:atIndexes:和-removeAtIndexes:(對應於 NSMutableArrayinsertObjects:atIndexes : 和removeObjectsAtIndexes:methods)。 如果至少一個插入方法和 至少一種去除方法被發現 每個的NSMutableArray消息發送到 收集代理對象將 結果在 -insertObject的一些組合:inAtIndex :, -removeObjectFromAtIndex :, -insert:atIndexes: ,以及-removeAtIndexes:發送到 mutableArrayValueForKey:的原始接收者的消息。 ...等...

這對我來說沒有任何意義,因爲它正在討論類似方法的「setter」。 mutableArrayValueForKey:返回一個NSMutableArray。上面列出的所有方法都返回void,並用於編輯NSMutableArray,而不是它。例如:

- (void)insertMyKey:(KeyClass *)keyObject inMyKeyAtIndex:(NSUInteger)index; 
- (void)removeObjectFromMyKeyAtIndex:(NSUInteger)index; 

任何想法蘋果試圖說在他們的文檔,或者如果這可能是一個錯誤?

我的理論是mutableArrayValueForKey:很有可能在搜索檢索KVC值時採取與valueForKey:類似的路徑。我只是不確定真正的路徑。

感謝您提供的任何幫助! :)

回答

21

你從哪打來mutableArrayValueForKey:找回NSMutableArray實際上是NSMutableArray私有子類覆蓋正常的排列方法,比如-count-objectAtIndex:-insertObject:atIndex:等,並調用該對象上相應的KVC方法將陣列從檢索。它基本上作爲操縱對象的一對多關係的代理,並且不需要擔心創建或返回自己。使用的一個快速示例:

Playlist* aPlaylist; 
Track* aTrack; 
NSMutableArray* mutableTracks = [aPlaylist mutableArrayValueForKey:@"tracks"]; 
[mutableTracks insertObject:aTrack atIndex:0]; 

這段代碼將一首曲目添加到播放列表的開頭。如果播放列表類爲其「跟蹤」關係實現KVC方法,則調用可變數組上的方法將導致在基礎對象上調用適當的方法。因此,在此示例中,當您在陣列上調用insertObject:atIndex:時,陣列將依次在播放列表對象上調用insertObjectInTracks:atIndex:,並將該軌道添加到播放列表的軌道數組中。

現在,在這個例子中,當然你可以直接調用insertObjectInTracks:atIndex:,但是你可以用mutableArrayValueForKey:代替它。

  • 數組包裝器隱藏了底層KVC方法的實現細節。實施完整的方法列表並非嚴格要求符合KVC。播放列表類可以實現-tracks-setTracks:,上面的代碼仍然可以工作。在這種情況下,代替調用insertObjectInTracks:atIndex:,可變數組代理將創建一個新數組,並在對象的開頭插入對象,然後在播放列表對象上調用setTracks:。這顯然效率較低,因此通常推薦實施完整的KVC方法列表。
  • 在密鑰的常量字符串替代變量的情況下,使用mutableArrayValueForKey:可以在不必知道要調用的方法的確切名稱的情況下操縱關係。只要該對象符合您使用的密鑰的KVC標準,所有內容都將「正常工作」。
  • 它還允許您使用任何方法,例如NSMutableArray自己實現,因此,例如,您可以使用搜索數組的對象,排序數組等方法,而不必重寫特殊版本來處理KVC的東西。
+0

感謝Brian,這非常有幫助。 :) – 2010-02-19 17:12:04

+1

「這段代碼添加了一首曲目到播放列表的開頭」,我認爲它在曲目的開頭添加了一首曲目,而不是播放列表? – 2010-09-03 08:41:35

+0

與使用綁定時相關的這種方法是相關的。在上面的例子中,如果Playlist是綁定到tracks數組的NSArrayController,並且我們有一個綁定到這個控制器的NSTableView,那麼爲了通過數組控制器將軌道上的變化反映到表中,我們必須從mutable數組代理,然後在該軌道上添加/刪除對象:事實上,這些操作將反映到將觸發綁定機制的KVC命令。 – viggio24 2011-10-04 19:26:39