[转][iOS]NSHashTable & NSMapTable
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
/ NSMutableSet
, NSHashTable
has the following characteristics:
NSSet
/NSMutableSet
holdsstrong
references to members, which are tested for hashing and equality using the methodshash
andisEqual:
.NSHashTable
is mutable, without an immutable counterpart.NSHashTable
can holdweak
references to its members.NSHashTable
cancopy
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 toNSPointerFunctionsStrongMemory
. This is the default behavior, equivalent toNSSet
member storage.NSHashTableWeakMemory
: Equal toNSPointerFunctionsWeakMemory
. Uses weak read and write barriers. UsingNSPointerFunctionsWeakMemory
, object references will turn toNULL
on last release.NSHashTableZeroingWeakMemory
: This option has been deprecated. Instead use theNSHashTableWeakMemory
option.NSHashTableCopyIn
: Use the memory acquire function to allocate and copy items on input (seeNSPointerFunction -acquireFunction
). Equal toNSPointerFunctionsCopyIn
.NSHashTableObjectPointerPersonality
: Use shifted pointer for the hash value and direct comparison to determine equality; use the description method for a description. Equal toNSPointerFunctionsObjectPointerPersonality
.
NSMapTable
NSMapTable
is a general-purpose analogue of NSDictionary
. Contrasted with the behavior of NSDictionary
/ NSMutableDictionary
, NSMapTable
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 withweak
references, in such a way that entries are removed when either the key or value is deallocated.NSMapTable
cancopy
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. UsingNSPointerFunctionsWeakMemory
, object references will turn toNULL
on last release. Equal toNSMapTableZeroingWeakMemory
.NSHashTableZeroingWeakMemory
: This option has been superseded by theNSMapTableWeakMemory
option.NSMapTableCopyIn
: Use the memory acquire function to allocate and copy items on input (see acquireFunction (seeNSPointerFunction -acquireFunction
). Equal to NSPointerFunctionsCopyIn.NSMapTableObjectPointerPersonality
: Use shifted pointer hash and direct equality, object description. Equal toNSPointerFunctionsObjectPointerPersonality
.
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
& NSMapTable
may be worth a look.
---------
作为delegate弱引用的集合再合适不过了。
[转][iOS]NSHashTable & NSMapTable的更多相关文章
- 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 ...
- ORA-01747: user.table.column, table.column 或列说明无效
Oracle.DataAccess.Client.OracleException ORA-01747: user.table.column, table.column 或列说明无效 原因1: 查了一下 ...
- SQLServer temporary table and table variable
Temporary tables are created in tempdb. The name "temporary" is slightly misleading, for ...
- Oracle10g 回收站及彻底删除table : drop table xx purge
drop后的表被放在回收站(user_recyclebin)里,而不是直接删除掉.这样,回收站里的表信息就可以被恢复,或彻底清除. 1.通过查询回收站user_recyclebin获取被删除的表信息, ...
- user.table.column, table.column 或列说明无效
Oracle统计采用别名出错(user.table.column, table.column 或列说明无效) >>>>>>>>>>>& ...
- lua中打印所以类型功能实现table嵌套table
lua中打印所以类型功能实现 本人測试 number.string.bool.nil.table嵌套table.userdata没问题 共享一下有什么问题请拍砖 代码例如以下 cclog = func ...
- 使用vue的v-for生成table , 给table加上序号
现在有一个使用mybatis的分页插件生成的table,table中数据是通过vue获得的 , 前台显示使用<tr v-for="item in items"> 后台v ...
- 表优化 altering table OPTIMIZE TABLE `sta_addr_copy`
表优化 altering table OPTIMIZE TABLE `sta_addr_copy` [总结] 1.实际测试的结果是,在state sqlaltering table OPTIMIZE ...
- 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 ...
随机推荐
- 苹果手机Safari无痕浏览模式下系统登录成功但是页面不跳转
昨天下午,测试提了一个bug,问题是:在苹果手机Safari无痕浏览模式下系统登录成功但是页面不跳转. 思前想后找了半天没思路,后来经过同事的点拨,说可能是禁用了cookie之类的,反正我也没思路就顺 ...
- 阿里云系列——6.给你的域名使用CDN加速(详细步骤+简单配置)
网站部署之~阿里云系列汇总 http://www.cnblogs.com/dunitian/p/4958462.html 进入管理页面:https://home.console.aliyun.com/ ...
- [SQL] SQL 基础知识梳理(二) - 查询基础
SQL 基础知识梳理(二) - 查询基础 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5904824.html 序 这是<SQL 基础知识梳理( ...
- IDDD 实现领域驱动设计-理解限界上下文
上一篇:<IDDD 实现领域驱动设计-理解领域和子域> <实现领域驱动设计>前两章内容,基本上读完了,和<领域驱动设计>不同的是,它把很多的概念都放在前面进行讲述了 ...
- DDD 领域驱动设计-如何完善 Domain Model(领域模型)?
上一篇:<DDD 领域驱动设计-如何 DDD?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 阅读目录: ...
- MySQL用户管理
主要总结MySQL进行用户管理的基本实现,包含MySQL登录,添加用户,删除用户,为用户分配权限,移除某用户的权限,修改密码,查看权限等基本操作,所有命令均亲测实现.本博文是本人的劳动成果所得,在博客 ...
- wordpress插件bug排查后记(记一次由于开启memecached引起的插件bug)
这篇文章是写给自己的. 周三的时候我在维护公司的一个wordpress项目页面时发现了一个非常奇怪的情况:当我尝试更新网站上的一个页面后,在wordpress后台的编辑器中发现其内容并没有按我预期的将 ...
- php内核分析(八)-zend_compile
这里阅读的php版本为PHP-7.1.0 RC3,阅读代码的平台为linux 回到之前看的zend_eval_stringl ZEND_API int zend_eval_stringl(char * ...
- 关于Quartz.NET作业调度框架的一点小小的封装,实现伪AOP写LOG功能
Quartz.NET是一个非常强大的作业调度框架,适用于各种定时执行的业务处理等,类似于WINDOWS自带的任务计划程序,其中运用Cron表达式来实现各种定时触发条件是我认为最为惊喜的地方. Quar ...
- NavisWorks Api 简单使用与Gantt
相信很多朋友在做BIM项目的时候.都有客户会提出项目计划,形象进度 等需求. 那么当前最主要的问题就是计划与BIM模型的关联问题.那么我在项目中是用户用Project软件编辑计划然后手动跟三维模型关联 ...