[转][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/NSMutableSetholdsstrongreferences to members, which are tested for hashing and equality using the methodshashandisEqual:.NSHashTableis mutable, without an immutable counterpart.NSHashTablecan holdweakreferences to its members.NSHashTablecancopymembers on input.NSHashTablecan 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 toNSSetmember storage.NSHashTableWeakMemory: Equal toNSPointerFunctionsWeakMemory. Uses weak read and write barriers. UsingNSPointerFunctionsWeakMemory, object references will turn toNULLon last release.NSHashTableZeroingWeakMemory: This option has been deprecated. Instead use theNSHashTableWeakMemoryoption.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/NSMutableDictionarycopies keys, and holds strong references to values.NSMapTableis mutable, without an immutable counterpart.NSMapTablecan hold keys and values withweakreferences, in such a way that entries are removed when either the key or value is deallocated.NSMapTablecancopyits values on input.NSMapTablecan 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 toNULLon last release. Equal toNSMapTableZeroingWeakMemory.NSHashTableZeroingWeakMemory: This option has been superseded by theNSMapTableWeakMemoryoption.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 & NSMapTablemay 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 ...
随机推荐
- Bootstrap3系列:按钮组
1. 基本实例 1.1 示例代码 <div class="btn-group"> <button type="button" class=&q ...
- ASP.NET Web API与Owin OAuth:调用与用户相关的Web API
在前一篇博文中,我们通过以 OAuth 的 Client Credential Grant 授权方式(只验证调用客户端,不验证登录用户)拿到的 Access Token ,成功调用了与用户无关的 We ...
- 【解决方案】cvc-complex-type.2.4.a: Invalid content was found starting with element 'init-param'. One of '{"http://java.sun.com/xml/ns/javaee":run-as, "http://java.sun.com/xml/ns/javaee":security-role-r
[JAVA错误] cvc-complex-type.2.4.a: Invalid content was found starting with element 'init-param'. One o ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统--工作流演示截图
- TextView使用大全
最近打算写一个系列的android初级开发教程,预计40篇以上的文章,结合我实际工作中的经验,写一些工作中经常用到的技术,让初学者可以少走弯路,写一个系列的话,大家学习起来也有头有尾. 今天就从我们每 ...
- JavaScript事件概览
JavaScript事件 JavaScript是单线程,在同一个时间点,不可能同时运行两个"控制线程". 事件句柄和事件对象 1.注册事件句柄 标准和非标准 var button= ...
- FFmpeg数据结构:AVPacket解析
本文主要从以下几个方面对AVPacket做解析: AVPacket在FFmpeg中的作用 字段说明 AVPacket中的内存管理 AVPacket相关函数的说明 结合AVPacket队列说明下AVPa ...
- PHPUnit整合ThinkPHP的库TPUnit
项目地址:https://github.com/web3d/TPUnit ThinkPHP PHPUnit框架集成,基于TP3.2,建议PHP 5.4以上环境. 单元测试应该是提高PHP编码质量的解决 ...
- enote笔记语言(1)
what 是什么 why 为什么 when 何时 where 在哪里 whi ...
- JAVA 日期格式工具类DateUtil.java
DateUtil.java package pers.kangxu.datautils.utils; import java.text.SimpleDateFormat; import java.ut ...