你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> NSHashTable的特性和使用

NSHashTable的特性和使用

編輯:IOS開發基礎

1.jpg

在看KVOController的代碼時,又看到了NSHashTable這個類,所以就此整理一下。

NSHashTable效仿了NSSet(NSMutableSet),但提供了比NSSet更多的操作選項,尤其是在對弱引用關系的支持上,NSHashTable在對象/內存處理時更加的靈活。相較於NSSet,NSHashTable具有以下特性:

  1. NSSet(NSMutableSet)持有其元素的強引用,同時這些元素是使用hash值及isEqual:方法來做hash檢測及判斷是否相等的。

  2. NSHashTable是可變的,它沒有不可變版本。

  3. 它可以持有元素的弱引用,而且在對象被銷毀後能正確地將其移除。而這一點在NSSet是做不到的。

  4. 它的成員可以在添加時被拷貝。

  5. 它的成員可以使用指針來標識是否相等及做hash檢測。

  6. 它可以包含任意指針,其成員沒有限制為對象。我們可以配置一個NSHashTable實例來操作任意的指針,而不僅僅是對象。

初始化NSHashTable時,我們可以設置一個初始選項,這個選項確定了這個NSHashTable對象後面所有的行為。這個選項是由NSHashTableOptions枚舉來定義的,如下所示:

enum {
    // 默認行為,強引用集合中的對象,等同於NSSet
    NSHashTableStrongMemory             = 0,
    // 在將對象添加到集合之前,會拷貝對象
    NSHashTableCopyIn                   = NSPointerFunctionsCopyIn,
    // 使用移位指針(shifted pointer)來做hash檢測及確定兩個對象是否相等;
    // 同時使用description方法來做描述字符串
    NSHashTableObjectPointerPersonality = NSPointerFunctionsObjectPointerPersonality,
    // 弱引用集合中的對象,且在對象被釋放後,會被正確的移除。
    NSHashTableWeakMemory               = NSPointerFunctionsWeakMemory 
};
typedef NSUInteger NSHashTableOptions;

當然,我們還可以使用NSPointerFunctions來初始化,但只有使用NSHashTableOptions定義的這些值,才能確保NSHashTable的各個API可以正確的工作—包括拷貝、歸檔及快速枚舉。

個人認為NSHashTable吸引人的地方在於可以持有元素的弱引用,而且在對象被銷毀後能正確地將其移除。我們來寫個示例:

// 具體調用如下
@implementation TestHashAndMapTableClass {
    NSMutableDictionary *_dic;
    NSSet               *_set;
    NSHashTable         *_hashTable;
}
- (instancetype)init {
    self = [super init];
    if (self) {
        [self testWeakMemory];
        NSLog(@"hash table [init]: %@", _hashTable);
    }
    return self;
}
- (void)testWeakMemory {
    if (!_hashTable) {
        _hashTable = [NSHashTable weakObjectsHashTable];
    }
    NSObject *obj = [[NSObject alloc] init];
    [_hashTable addObject:obj];
    NSLog(@"hash table [testWeakMemory] : %@", _hashTable);
}

這段代碼的輸出結果如下:

hash table [testWeakMemory] : NSHashTable {
[6] }
hash table [init]: NSHashTable {
}

可以看到,在離開testWeakMemory方法,obj對象被釋放,同時對象在集合中的引用也被安全的刪除。

這樣看來,NSHashTable似乎比NSSet(NSMutableSet)要好啊。那是不是我們就應用都使用NSHashTable呢?Peter Steinberger在The Foundation Collection Classes給了我們一組數據,顯示在添加對象的操作中,NSHashTable所有的時間差不多是NSMutableSet的2倍,而在其它操作中,性能大體相近。所以,如果我們只需要NSSet的特性,就盡量用NSSet。

另外,Mattt Thompson在NSHashTable & NSMapTable的結尾也寫了段挺有意思的話,在此直接摘抄過來:

As always, it's important to remember that programming is not about being clever: always approach a problem from the highest viable level of abstraction. NSSet and NSDictionary are great classes. For 99% of problems, they are undoubtedly the correct tool for the job. If, however, your problem has any of the particular memory management constraints described above, then NSHashTable & NSMapTable may be worth a look.

參考

  1. NSHashTable Class Reference

  2. NSHashTable & NSMapTable

  3. NSHashTable & NSMapTable

  4. The Foundation Collection Classes

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved