2010-12-05 123 views
2

我正在嘗試創建一個半複雜的視圖動畫集(想想NSMatrix表單的動畫版本,其中行隨着其他行的添加或刪除而滑動),並構建我製作的動畫助手類。使用NSView實例作爲NSDictionary鍵?

在那裏,我必須跟蹤不同的視圖,它們的有序索引以及與它們的動畫相關的一些其他值。

爲此,我使用NSArray實例來跟蹤視圖的排序(索引),並且我想使用帶有視圖的NSDictionary作爲鍵來跟蹤值(值本身在嵌套字典中)。即我希望能夠做到這事,例如(僞代碼):

NSMutableDictionary* viewValuesDict = [NSDictionary dictionary]; 

// Loop thru an ordered NSArray 
for((NSView*) view in viewsArray) { 
    // Get some values we'll need later 
    NSDictionary* associatedValues = [view getSomeValues]; 

    // ...and put them into viewValuesDict... 
    [viewValuesDict setObject:associatedValues forKey:view]; 

    // and then things break because the NSView 'view' 
    // doesn't support copyWithZone.... darn 
} 

問題是,我當然不能用NSView實例作爲字典鍵,因爲鍵使用添加的copyWithZone,其中NSView未執行。

那麼,什麼是獲得NSView實例的唯一密鑰的好方法?我可以想象使用[obj description],因爲你獲得的內存地址是一個完美的UID,但是當然系統必須與任何類型的NSView子類一起工作,這可能會完全返回其他東西,所以這沒有用。

或者我應該嘗試一些其他的東西?有沒有可能替代NSDictionary,鑰匙只是不復制?因爲在這種情況下,我真的不需要複製密鑰。

回答

8

有時會出現一些情況,您希望使用視圖(無論是NS還是UI)作爲詞典中的鍵。我遇到過這種情況。我寧願使用objc_setAssociatedObject,但這需要雪豹。與NSValue拳擊將工作,但如果你需要做很多很多的查找視圖,連續拳擊和拆箱的指針可能會變得乏味。

有兩種選擇來創建NSView => <object>字典。

  1. 使用NSMapTable
  2. 使用CFMutableDictionaryRef

NSMapTable是10.5推出的一類,這是非常類似於NSMutableDictionary,除了它具有額外的能力,使得它與垃圾收集更多的工作很好。在你的情況下,你可能會想要一個帶有「弱」鍵和「強」值的映射表,但閱讀所有有趣細節的文檔。

CFMutableDictionaryRefNSDictionary的核心基金會等價物(它們是免費橋接的),但它有一些額外的創建選項。您使用CFDictionaryCreateMutable()創建一個,並且需要兩個struct參數。一種是定義如何處理字典鍵的內存管理(和其他)行爲的結構,另一種是定義值行爲的struct。您可以創建一個CFMutableDictionaryRef,其中包含保留鍵(而不是複製它們)然後保留這些值的選項。完成此操作後,您可以將CFMutableDictionaryRef轉換爲NSMutableDictionary並按照您的預期使用它,只需保留這些密鑰而不是複製。

0

創建您的字典,以便其中一個值是視圖;然後重新排列代碼,以便不必根據視圖查找詞典,而是從詞典或索引開始(將詞典放入數組中)或者自己創建的唯一ID(將詞典放入字典;對於每個新視圖,ID可以像連續數字一樣簡單,然後開始跟蹤)。除非你正在做一些非常複雜和動態的事情,否則應該可以避免只需要查詢NSView

+0

謝謝。是的,我也在想這個。我只是想到,只有使用任何ol對象作爲關鍵的方法。看起來(至少對我來說)使用對象作爲鍵將是一個簡單的方法來「僞造」對象上的一些額外屬性(我希望類別會以某種方式讓你添加ivars ......嘆息)。 – Flambino 2010-12-05 21:39:59

+0

不是。鍵具有真正特定的屬性;這正是使字典有效的原因。如果你真的想爲每個NSView添加一些額外的屬性,爲什麼不是繼承?這正是子類的用途! – andyvn22 2010-12-06 03:41:06

+0

因爲代碼必須在任何視圖上運行,而不僅僅是特定的子類。此外,它只是在很短的時間內存儲一些相關的值(足夠長的時間來準備生成的NSViewAnimation,但就是這樣),所以雖然我可以做一些對象組合幷包裝NSViews,但它看起來像是矯枉過正。無論如何,NSMapTable工作出色:-) – Flambino 2010-12-06 09:44:14

1

正如andyvn22所說,重組!但是,如果這不實際:

  • 如果您的目標是雪豹,並且關聯可能會在視圖的整個生命週期內持續存在,請使用objc_setAssociatedObject()
  • 否則,請使用[NSValue valueWithNonretainedObject:]而不是-description。 (像它說,它不保留對象,但你的陣列一樣。)
+0

重組可以完成,但我希望有一個快捷方式:-)我的目標是雪豹,但我只需要很短的時間內的值,所以我認爲,我會跳過`objc_setAssociatedObject()`。但`valueWithNonretainedObject:`可能是要走的路。我會試試看 - 謝謝! – Flambino 2010-12-05 21:44:55

2

使用NSMapTable,而不是NSDictionary(當然你必須確保,如果你仔細管理對象生存不使用垃圾收集)。 This article對如何使用它有很好的總結。

相關問題