[转] NSMapTable 不只是一个能放weak指针的 NSDictionary
NSMapTable 不只是一個能放weak指針的 NSDictionary
NSMapTable是早在Mac OS X 10.5(Leopard)的引入集合類。乍一看,這似乎是作為一個替換NSDictionary的存在,可以選擇“strong”和“week”指針。 在這篇文章中,我會告訴你除了為什么它也非常有用之外的還有垃圾回收機(jī)制以及它是如何做NSDictionary中不能(或不應(yīng)該)做的事情。
轉(zhuǎn)至 ?http://www.isaced.com/post-235.html
?
Leopard 中更多的Cocoa API
可可增加了幾個新的集合類在Mac OS X 10.5(Leopard)的。這些措施包括:
- NSPointerArray
- NSHashTable
- NSMapTable
NSPointerArray完全是新的,但大部分的 NSHashTable 和 NSMapTable 的功能之前可從 opaque Foundation C structs of the same names 看到。
在某些方面,這些新的類,像NSMutableArray, NSMutableSet和的NSMutableDictionary一樣工作,但是給了你使用“week”垃圾回收指針的選擇。如果您使用的 Objective-C 2.0 垃圾回收機(jī)制,你應(yīng)該知道什么是使用“week”指針,因此使用此選項(xiàng)的優(yōu)勢應(yīng)該是清楚的。
NSPointerArray也可用于純指針(指針不一定是Objective-C的類),但NSHashTable和的NSMutableArray類都需要它們的內(nèi)容是Objective-C的對象。
雖然在一般意義上,NSPointerArray and NSHashTable 被設(shè)計為可以替換 NSMutableArray and NSMutableSet 的角色(有序和無序陣列)。
NSMapTable則是不同的,因?yàn)樗梢栽谀愕脑O(shè)計中使用,而NSMutableDictionary不能(或不應(yīng)該)。
?
NSDictionary的局限性
NSDictionary提供了key-to-object的映射。從本質(zhì)上講,NSDictionary中存儲的object位置是由“key”來索引的。
由于對象存儲在特定位置,NSDictionary中要求key的值不能改變(否則object的位置會突然錯誤)。為了保證這一點(diǎn),NSDictionary中始終復(fù)制key到它私有位置。
這個key的復(fù)制行為也是NSDictionary如何工作的基礎(chǔ),但這也有一個限制:你可以只使用Objective-C對象作為 NSDictionary的key,如果它支持NSCopying協(xié)議。此外,key應(yīng)該是小且高效的,以至于復(fù)制的時候不會對CPU和內(nèi)存造成負(fù)擔(dān)。
這意味著,NSDictionary中真的只有適合“value”類型的對象作為key(如簡短字符串和數(shù)字)。這不是離線的對象到對象的映射模型。
?
對象到對象的映射
NSMapTable(顧名思義)更適合于一般意義的映射。這取決于它是如何構(gòu)造的,NSMapTable可以處理的“key-to-object”樣式映射的NSDictionary,但它也可以處理“object-to-object”的映射 - 也被稱為“associative array”或簡稱為“map”。
例如,一個NSMapTable構(gòu)造如下:
NSMapTable *keyToObjectMapping =[NSMapTablemapTableWithKeyOptions:NSMapTableCopyInvalueOptions:NSMapTableStrongMemory];將會和NSMutableDictionary工作得一樣一樣的,復(fù)制其“key”,并retaining它的“object”。
一個純粹的對象到對象(object-to-object)的映射可以構(gòu)造如下:
NSMapTable *objectToObjectMapping =[NSMapTable mapTableWithStrongToStrongObjects];一個對象到對象(object-to-object)的行為可能以前可以用NSDictionary來模擬,如果所有的key都是一個 NSNumber包含于該映射的源對象的內(nèi)存地址(不要笑,我見過這種情況),但這些內(nèi)存地址都是奔波在外,Cocoa中首次提供了一個真正的對象到對象 的映射NSMapTable。
?
NSMapTable的選項(xiàng)
NSMapTable提供的選項(xiàng)是由三部分組成:一個“memory option”(內(nèi)存選項(xiàng)),一個“personality option”和“copy in”標(biāo)志。你可以為每個部分使用一個選項(xiàng)(如果沒有提供一個選項(xiàng)的部分將會使用默認(rèn)行為),這個部分都是位標(biāo)志(bit flag)(二進(jìn)制 “or” 合并在一起)。
理論上,NSMapTable允許以下選項(xiàng):
- NSMapTableStrongMemory (a "memory option")
- NSMapTableWeakMemory (a "memory option")
- NSMapTableObjectPointerPersonality (a "personality option")
- NSMapTableCopyIn (a "copy option")
NSMapTableStrongMemory是默認(rèn)的“memory option”。然而,默認(rèn)的“personality option”,默認(rèn)“copy in”的行為沒有名字那么這兩個值可以被視為隱含在列表中。
memory option
Objective-C使用“strong”和“week”作為垃圾回收機(jī)制相關(guān)的術(shù)語,它可能不是很明顯,這些選項(xiàng)可以在垃圾回收機(jī)制代碼之外使用(蘋果稱它為手動內(nèi)存管理)。
在垃圾回收機(jī)制外,他們被定義為:
- strong: 使用 retain 和 release
- weak: 不使用 retain 和 release
NSMapTable只允許NSPointerFunctionsOptions對應(yīng)的Objective-C對象“personality option”。還有其他NSPointerFunctionsOptions “personality option”里的“strong”指針的行為不包括retain和release,但這些選項(xiàng)在NSMapTable都是不允許的。
關(guān)于使用垃圾回收機(jī)制的“week”之外的警告:
指針將不會被歸零如在垃圾回收環(huán)境所以你必須要小心,不要取消引用指針,如果它被釋放。
Personality options
該NSMapTableObjectPointerPersonality選項(xiàng)用來控制是否isEqualTo:和哈希對象中的方法添加的對象添加到集合時使用。
- NSMapTableObjectPointerPersonality指定
對象的指針的值是用于直接比較和位移哈希生成(isEqualTo:和散列方法是不使用)。 - NSMapTableObjectPointerPersonality 不指定(默認(rèn)行為)
的哈希值與isEqualTo:方法會在調(diào)用的關(guān)鍵在確定的存儲位置NSMapTable。這些方法的返回值不應(yīng)改變(是不可變)為主要用在時間NSMapTable。
兩行為暗示內(nèi)容實(shí)現(xiàn)了NSObject的協(xié)議,所以在這個協(xié)議方法也可以在key和object調(diào)用。特別地,描述的方法可以在被調(diào)用NSMapTable包含密鑰和對象無論使用的“Personality options”。該NSMapTable將只支持NSCoding如果所有的key和object實(shí)現(xiàn)了NSCoding協(xié)議了。
Copy options
如果NSMapTableCopyIn被指定,當(dāng)NSCopying協(xié)議被加入時NSMapTable使用使自己的數(shù)據(jù)副本。如果不指定此選項(xiàng)(默認(rèn)行為)將不會復(fù)制。
翻譯自:NSMapTable: more than an NSDictionary for weak pointers
這篇文章雖然很久了(2008年),但就算放在當(dāng)下也是很有學(xué)習(xí)價值的,感謝Google translate,感謝Baidu translate!
?
?
?
總結(jié)
以上是生活随笔為你收集整理的[转] NSMapTable 不只是一个能放weak指针的 NSDictionary的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用opencv抽取视频的帧并保存为连续的
- 下一篇: JavaScript学习总结(十三)——