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. My First Android Application Project 第一个安卓应用

    一.前言: 安卓(Android):是一种基于Linux的自由及开放源代码的操作系统,主要用在移动设备上,如手机.平板电脑.其他的设备也有使用安卓操作系统,比如:电视机,游戏机.数码相机等等. 二.具 ...

  2. 锋利的jQuery--表单等(读书笔记三)

    1.input元素中的多选的,单选,不选,涉及属性checked   2.select元素中的选中,涉及selected   3.表单的验证   4.表格隔行变色 $("tr:odd&quo ...

  3. 一个技术汪的开源梦 —— 基于 .Net Core 的公共组件之 Http 请求客户端

    一个技术汪的开源梦 —— 目录 想必大家在项目开发的时候应该都在程序中调用过自己内部的接口或者使用过第三方提供的接口,咱今天不讨论 REST ,最常用的请求应该就是 GET 和 POST 了,那下面开 ...

  4. 【分布式】Zookeeper使用--开源客户端

    一.前言 上一篇博客已经介绍了如何使用Zookeeper提供的原生态Java API进行操作,本篇博文主要讲解如何通过开源客户端来进行操作. 二.ZkClient ZkClient是在Zookeepe ...

  5. Signalr系列之虚拟目录详解与应用中的CDN加速实战

    目录 对SignalR不了解的人可以直接移步下面的目录 SignalR系列目录 前言 前段时间一直有人问我 在用SignalR 2.0开发客服系统[系列1:实现群发通讯]这篇文章中的"/Si ...

  6. 【读fastclick源码有感】彻底解决tap“点透”,提升移动端点击响应速度

    申明!!!最后发现判断有误,各位读读就好,正在研究中.....尼玛水太深了 前言 近期使用tap事件为老夫带来了这样那样的问题,其中一个问题是解决了点透还需要将原来一个个click变为tap,这样的话 ...

  7. 简简单单学会C#位运算

    一.理解位运算 要学会位运算,首先要清楚什么是位运算?程序中的所有内容在计算机内存中都是以二进制的形式储存的(即:0或1),位运算就是直接对在内存中的二进制数的每位进行运算操作 二.理解数字进制 上面 ...

  8. Yii 2.x Behavior - 类图

    yii\base\Component  继承这个类的类都具备扩展行为的能力

  9. Java 内存区域与内存溢出

    内存区域 Java 虚拟机在执行 Java 程序的过程中会把他所管理的内存划分为若干个不同的数据区域.Java 虚拟机规范将 JVM 所管理的内存分为以下几个运行时数据区:程序计数器.Java 虚拟机 ...

  10. 遍历datatable的方法汇总

    遍历datatable的方法方法一: DataTable dt = dataSet.Tables[]; ; i < dt.Rows.Count ; i++) { string strName = ...