NSHashTable和NSMapTable用法

發表於2016-08-30

一個專案中的需求


在iOS專案開發過程中,我們經常會使用到NSSetNSArrayNSDictionary三個類,它們為我們設計較友好的資料結構時提供了很方便的方法

先準備本文中將要使用的物件:

在程式開發過程中,經常會用到諸如此類的Model物件.
用法呢也大致會有如下幾種方式:
1.通過有序的數列進行儲存,陣列NSArray;

輸出的結果如下:

2.通過統一的關鍵字進行儲存,字典NSDictionary;

輸出的結果如下:


通過上述兩個例子我們能夠發現一個問題,即將物件新增到容器時,會對該物件的引用技術+1
這樣就會有可能發生迴圈持有的問題,例如如下程式碼:

在以上程式碼中,一個human的例項物件中包含一個strong修飾的family屬性,但是在family屬性中,又新增了human自身物件,這樣會造成迴圈持有的問題,而導致記憶體洩漏。
但是專案需求又要求我們在該Model物件中完成如此程式碼,我們不得已會多建立一個類HHHumanRelationShip,如下所示:


NSHashTable


很明顯,大家能夠看到這樣造成了程式程式碼的臃腫
根據上述需求和功能,在iOS6之後,Objective-C Foundation框架中新增了兩個類分別是NSHashTableNSMapTable

  • NSHashTable
    • 建構函式
      • - (instancetype)initWithOptions:(NSPointerFunctionsOptions)options capacity:(NSUInteger)initialCapacity
      • - (instancetype)initWithPointerFunctions:(NSPointerFunctions *)functions capacity:(NSUInteger)initialCapacity
      • + (NSHashTable *)hashTableWithOptions:(NSPointerFunctionsOptions)options;
      • + (id)hashTableWithWeakObjects;
      • + (NSHashTable *)weakObjectsHashTable;

在建立NSHashTable物件時,會傳NSPointerFunctionsOptions引數,列舉如下:

  • NSHashTableStrongMemory
    • 將HashTable容器內的物件引用計數+1一次
  • NSHashTableZeroingWeakMemory
    • 在OSX 10.8之後已經廢棄
  • NSHashTableCopyIn
    • 將新增到容器的物件通過NSCopying中的方法,複製一個新的物件存入HashTable容器
  • NSHashTableObjectPointerPersonality
    • 使用移位指標(shifted pointer)來做hash檢測及確定兩個物件是否相等;
  • NSHashTableWeakMemory
    • 不會修改HashTable容器內物件元素的引用計數,並且物件釋放後,會被自動移除

對於我們來說,NSHashTable吸引力比較大的即NSHashTableWeakMemory特性.
使用一段程式碼來展示功能:

在控制檯輸出的結果如下

我們可以看到,當pool物件釋放時,human的引用計數會執行一次-1,human物件在記憶體中就會自動釋放,並且相應的hash_tab物件中的物件也會被自動移除.
而我們在建立hash_tab時使用的是NSHashTableStrongMemory特性話,那麼控制檯輸出的結果如下:

有了NSHashTable就可以完成我們文章一開始的需求了.

NSHashTable可以使用的函式


NSMapTable


  • NSMapTable
    • 建構函式
      • - (instancetype)initWithKeyOptions:(NSPointerFunctionsOptions)keyOptions valueOptions:(NSPointerFunctionsOptions)valueOptions capacity:(NSUInteger)initialCapacity;
      • - (instancetype)initWithKeyPointerFunctions:(NSPointerFunctions *)keyFunctions valuePointerFunctions:(NSPointerFunctions *)valueFunctions capacity:(NSUInteger)initialCapacity;
      • + (NSMapTable *)mapTableWithKeyOptions:(NSPointerFunctionsOptions)keyOptions valueOptions:(NSPointerFunctionsOptions)valueOptions;
      • + (NSMapTable *)strongToStrongObjectsMapTable;
      • + (NSMapTable *)weakToStrongObjectsMapTable;
      • + (NSMapTable *)strongToWeakObjectsMapTable;
      • + (NSMapTable *)weakToWeakObjectsMapTable;

NSMapTable物件類似與NSDictionary的資料結構,但是NSMapTable功能比NSDictionary物件要多的功能就是可以設定keyvalue的NSPointerFunctionsOptions特性!其他的用法與NSDictionary相同.

NSMapTable可以使用的函式

相關文章