NSSet and NSDictionary, along with NSArray are the workhorse collection classes of Foundation. Unlike other standard libraries, implementation details are hidden from developers, allowing them to write simple code and trust that it will be (reasonably) performant.

However, even the best abstractions break down; their underlying assumptions overturned. In these cases, developers either venture further down the abstraction, or, if available use a more general-purpose solution.

For NSSet and NSDictionary, the breaking assumption was in the memory behavior when storing objects in the collection. For NSSet, objects are a strongly referenced, as are NSDictionary values. Keys, on the other hand, are copied by NSDictionary. If a developer wanted to store a weak value, or use a non-<NSCopying>-conforming object as a key, they could be clever and use NSValue +valueWithNonretainedObject. Or, as of iOS 6 (and as far back as OS X Leopard), they could use NSHashTable or NSMapTable, the more general-case counterparts to NSSet or NSDictionary, respectively.

So without further ado, here's everything you need to know about two of the more obscure members of Foundation's collection classes:

NSHashTable

NSHashTable is a general-purpose analogue of NSSet. Contrasted with the behavior of NSSet / NSMutableSetNSHashTable has the following characteristics:

  • NSSet / NSMutableSet holds strong references to members, which are tested for hashing and equality using the methods hash and isEqual:.
  • NSHashTable is mutable, without an immutable counterpart.
  • NSHashTable can hold weak references to its members.
  • NSHashTable can copy members on input.
  • NSHashTable can contain arbitrary pointers, and use pointer identity for equality and hashing checks.

Usage

NSHashTable *hashTable = [NSHashTable hashTableWithOptions:NSPointerFunctionsCopyIn];
[hashTable addObject:@"foo"];
[hashTable addObject:@"bar"];
[hashTable addObject:@42];
[hashTable removeObject:@"bar"];
NSLog(@"Members: %@", [hashTable allObjects]);

NSHashTable objects are initialized with an option for any of the following behaviors. Deprecated enum values are due to NSHashTable being ported from Garbage-Collected OS X to ARC-ified iOS. Other values are aliased to options defined by NSPointerFunctions, which will be covered next week on NSHipster.

  • NSHashTableStrongMemory: Equal to NSPointerFunctionsStrongMemory. This is the default behavior, equivalent to NSSet member storage.
  • NSHashTableWeakMemory: Equal to NSPointerFunctionsWeakMemory. Uses weak read and write barriers. Using NSPointerFunctionsWeakMemory, object references will turn to NULL on last release.
  • NSHashTableZeroingWeakMemory: This option has been deprecated. Instead use the NSHashTableWeakMemory option.
  • NSHashTableCopyIn: Use the memory acquire function to allocate and copy items on input (see NSPointerFunction -acquireFunction). Equal to NSPointerFunctionsCopyIn.
  • NSHashTableObjectPointerPersonality: Use shifted pointer for the hash value and direct comparison to determine equality; use the description method for a description. Equal to NSPointerFunctionsObjectPointerPersonality.

NSMapTable

NSMapTable is a general-purpose analogue of NSDictionary. Contrasted with the behavior of NSDictionary / NSMutableDictionaryNSMapTable has the following characteristics:

  • NSDictionary / NSMutableDictionary copies keys, and holds strong references to values.
  • NSMapTable is mutable, without an immutable counterpart.
  • NSMapTable can hold keys and values with weak references, in such a way that entries are removed when either the key or value is deallocated.
  • NSMapTable can copy its values on input.
  • NSMapTable can contain arbitrary pointers, and use pointer identity for equality and hashing checks.

Usage

Instances where one might use NSMapTable include non-copyable keys and storing weak references to keyed delegates or another kind of weak object.

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

NSMapTable objects are initialized with options specifying behavior for both keys and values, using the following enum values:

  • NSMapTableStrongMemory: Specifies a strong reference from the map table to its contents.
  • NSMapTableWeakMemory: Uses weak read and write barriers appropriate for ARC or GC. Using NSPointerFunctionsWeakMemory, object references will turn to NULL on last release. Equal to NSMapTableZeroingWeakMemory.
  • NSHashTableZeroingWeakMemory: This option has been superseded by the NSMapTableWeakMemory option.
  • NSMapTableCopyIn: Use the memory acquire function to allocate and copy items on input (see acquireFunction (see NSPointerFunction -acquireFunction). Equal to NSPointerFunctionsCopyIn.
  • NSMapTableObjectPointerPersonality: Use shifted pointer hash and direct equality, object description. Equal to NSPointerFunctionsObjectPointerPersonality.

Subscripting

NSMapTable doesn't implement object subscripting, but it can be trivially added in a category. NSDictionary's NSCopying requirement for keys belongs to NSDictionary alone:

@implementation NSMapTable (NSHipsterSubscripting)

- (id)objectForKeyedSubscript:(id)key
{
return [self objectForKey:key];
} - (void)setObject:(id)obj forKeyedSubscript:(id)key
{
[self setObject:obj forKey:key];
} @end

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 & NSMapTablemay be worth a look.

---------

作为delegate弱引用的集合再合适不过了。

转自:http://nshipster.com/nshashtable-and-nsmaptable/

[转][iOS]NSHash​Table & NSMap​Table的更多相关文章

  1. mysqldump:Couldn't execute 'show create table `tablename`': Table tablename' doesn't exist (1146)

    遇到了一个错误mysqldump: Couldn't execute 'show create table `CONCURRENCY_ERRORS`': Table INVOICE_OLD.CONCU ...

  2. ORA-01747: user.table.column, table.column 或列说明无效

    Oracle.DataAccess.Client.OracleException ORA-01747: user.table.column, table.column 或列说明无效 原因1: 查了一下 ...

  3. SQLServer temporary table and table variable

    Temporary tables are created in tempdb.  The name "temporary" is slightly misleading, for ...

  4. Oracle10g 回收站及彻底删除table : drop table xx purge

    drop后的表被放在回收站(user_recyclebin)里,而不是直接删除掉.这样,回收站里的表信息就可以被恢复,或彻底清除. 1.通过查询回收站user_recyclebin获取被删除的表信息, ...

  5. user.table.column, table.column 或列说明无效

    Oracle统计采用别名出错(user.table.column, table.column 或列说明无效) >>>>>>>>>>>& ...

  6. lua中打印所以类型功能实现table嵌套table

    lua中打印所以类型功能实现 本人測试 number.string.bool.nil.table嵌套table.userdata没问题 共享一下有什么问题请拍砖 代码例如以下 cclog = func ...

  7. 使用vue的v-for生成table , 给table加上序号

    现在有一个使用mybatis的分页插件生成的table,table中数据是通过vue获得的 , 前台显示使用<tr v-for="item in items"> 后台v ...

  8. 表优化 altering table OPTIMIZE TABLE `sta_addr_copy`

    表优化 altering table OPTIMIZE TABLE `sta_addr_copy` [总结] 1.实际测试的结果是,在state sqlaltering table OPTIMIZE ...

  9. MySQL check table/optimize table/analyze table/REPAIR TABLE

    MySQL check table/optimize table/analyze table/REPAIR TABLE 转自:https://www.cnblogs.com/datastack/p/3 ...

随机推荐

  1. 使用Red Gate Sql Compare 数据库同步工具进行SQL Server的两个数据库的结构比较、同步

    将测试版的项目同步(部署)到正式版的时候,两个数据库的结构比较与同步时,如果修改数据库的时候没有记录好修改了那些表,很难将两个数据库进行同步 RedGate Sql Compare使用简介说明: 1. ...

  2. <JavaScript语言精粹>-读书笔记(一)

    用object.hasOwnProperty(variable)来确定这个属性名是否为该对象成员,还是来自于原型链. for(my in obj){ if(obj.hasOwnProperty(my) ...

  3. Python开发环境配置

    好久没有写博客了,自从6月份毕业后,进入一家做书法.字画文化宣传的互联网公司(www.manyiaby.com),这段时间一直在进行前端开发,对于后端的使用很少了,整天都是什么html.css.jav ...

  4. scikit-learn随机森林调参小结

    在Bagging与随机森林算法原理小结中,我们对随机森林(Random Forest, 以下简称RF)的原理做了总结.本文就从实践的角度对RF做一个总结.重点讲述scikit-learn中RF的调参注 ...

  5. Set容器--HashSet集合

    Set容器特点: ①   Set容器是一个不包含重复元素的Collection,并且最多包含一个null元素,它和List容器相反,Set容器不能保证其元素的顺序; ②   最常用的两个Set接口的实 ...

  6. PHP的学习--使用phar打包

    前段时间写了几个PHP的脚本,但是因为脚本的项目是基于composer安装的,给别人使用的时候不太方便,就希望能够打包成一个能直接使用的文件. 搜索了一下,发现可以使用phar打包. 假设我们有如下一 ...

  7. 解决新版Android studio导入微信支付和支付宝官方Demo的问题

    最近项目要用到支付宝支付和微信支付,本想使用第三方支付框架ping++或者BeeCloud的,但是由于他们的收费问题,让我望而却步,而且公司给了相应的公钥.私钥和APPID等,所以就用下开放平台的呗. ...

  8. 由css reset想到的深入理解margin及em的含义

    由css reset想到的深入理解margin及em的含义 原文地址:http://www.ymblog.net/content_189.html 经常看到这样语句,*{ margin:0px;pad ...

  9. asp.net core 依赖注入问题

    最近.net core可以跨平台了,这是一个伟大的事情,为了可以赶上两年以后的跨平台部署大潮,我也加入到了学习之列.今天研究的是依赖注入,但是我发现一个问题,困扰我很久,现在我贴出来,希望可以有人帮忙 ...

  10. 学习Redis你必须了解的数据结构——双向链表(JavaScript实现)

    本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文链接 http://www.cnblogs.com/tdws/ 下午分享了JavaScript实现单向链表,晚上就来补充下双向链表吧.对链表 ...