发布于 

NSHashTable 和 NSMapTable

NSSet,NSDictionary,NSArray 是 Foundation 框架关于集合操作的常用类。在 NSSet 中,objects 是被强引用的(strongly referenced),同样 NSDictionary 中的 keys 和 values 也会被 NSDictionary 复制。如果我们想要存储一个 weak 类型的值或者使用一个没有实现 NSCopying 协议的 object 作为 NSDictionary 的 key,就可以分别使用和 NSSet,NSDictionary 地位相同的 NSHashTable,NSMapTable。

NSHashTable

NSHashTable 是更广泛意义的 NSSet,NSHashTable 相比 NSSet/NSMutableSet 有如下特性:

  • NSHashTable 是可变的
  • NSHashTable 可以持有 weak 类型的成员变量
  • NSHashTable 可以在添加成员变量是复制成员
  • NSHashTable 可以随意存储指针并利用指针的唯一性来进行 hash 查重和对比(equal)操作

用法示例:

1
2
3
4
5
6
NSHashTable *hashTable = [NSHashTable hashTableWithOptions:NSPointerFunctionsCopyIn];
[hashTable addObject:@"a"];
[hashTable addObject:@"b"];
[hashTable addObject:@11];
[hashTable removeObject:@"b"];
NSLog(@"Items: %@", [hashTable allObjects]);

NSHashTable 是根据一个 option 参数来进行初始化,option 可选项有:

  • NSHashTableStrongMemory:对成员变量进行强引用,这是一个默认值,如果采用这个默认值,NSHashTable 和 NSSet 就没有了区别。
  • NSHashTableWeakMemory:对成员变量进行弱引用,object 引用在最后释放的时候会被指向 NULL。
  • NSHashTableCopyIn:在对象被加入集合之前进行复制。
  • NSHashTableObjectPointerPersonality:用指针来等同代替实际的值,当打印这个指针的时候相当于调用 description 方法。
  • NSHashTableZeroingWeakMemory:已被抛弃,使用 NSHashTableWeakMemory 代替。

NSMapTable

NSDictionary/NSMutableDictionary 会复制 keys 并通过强引用 values 来实现存储。NSMapTable 是更广泛意义的 NSDictionary。NSMapTable 相比 NSDictionary/NSMutableDictionary 有如下特性:

  • NSMapTable 是可变的。
  • NSMapTable 可以通过弱引用来持有 keys 和 values。当 key 或 value 被 deallocated 时,对应存储的内容也会被移除。
  • NSMapTable 可以在添加 value 的时候对 value 进行复制。

NSMapTable 和 NSHashTable 类似,可以随意的存储指针,并利用指针的唯一性来进行 hash 查重。

应用

假设用 NSMapTable 来存储不用被复制的 keys 和被若引用的 value,这里的 value 就可以是某个 delegate 或者一种弱类型。

1
2
3
4
5
id delegate = ...;
NSMapTable *mapTable = [NSMapTable mapTableWithKeyOptions:NSMapTableStrongMemory
valueOptions:NSMapTableWeakMemory];
[mapTable setObject:delegate forKey:@"foo"];
NSLog(@"Keys: %@", [[mapTable keyEnumerator] allObjects]);

总结

日常开发过程中 NSSet 和 NSDictionary 可以解决我们的大多数需求,如果有内存相关处理问题时,可以借助于 NSHashTable 和 NSMapTable。

参考内容:


本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 @JonyFang 创建,使用 Stellar 作为主题,您可以在 GitHub 找到本站源码。