[转] NSMapTable 不只是一个能放weak指针的 NSDictionary

NSMapTable
不只是一个能放weak指针的 NSDictionary

NSMapTable是早在Mac OS X
10.5(Leopard)的引入集合类。乍一看,这似乎是作为一个替换NSDictionary的存在,可以选择“strong”和“week”指针。
在这篇文章中,我会告诉你除了为什么它也非常有用之外的还有垃圾回收机制以及它是如何做NSDictionary中不能(或不应该)做的事情。

转至
 http://www.isaced.com/post-235.html

Leopard 中更多的Cocoa
API

可可增加了几个新的集合类在Mac OS X 10.5(Leopard)的。这些措施包括:

NSPointerArray完全是新的,但大部分的 NSHashTable
NSMapTable 的功能之前可从 opaque Foundation C structs of the same names 看到。

在某些方面,这些新的类,像NSMutableArray
NSMutableSet和的NSMutableDictionary一样工作,但是给了你使用“week”垃圾回收指针的选择。如果您使用的
Objective-C 2.0 垃圾回收机制,你应该知道什么是使用“week”指针,因此使用此选项的优势应该是清楚的。

NSPointerArray也可用于纯指针(指针不一定是Objective-C的类),但NSHashTable和的NSMutableArray类都需要它们的内容是Objective-C的对象。

虽然在一般意义上,NSPointerArray and NSHashTable 被设计为可以替换 NSMutableArray and
NSMutableSet 的角色(有序和无序阵列)。

NSMapTable则是不同的,因为它可以在你的设计中使用,而NSMutableDictionary不能(或不应该)。

NSDictionary的局限性

NSDictionary提供了key-to-object的映射。从本质上讲,NSDictionary中存储的object位置是由“key”来索引的。

由于对象存储在特定位置,NSDictionary中要求key的值不能改变(否则object的位置会突然错误)。为了保证这一点,NSDictionary中始终复制key到它私有位置。

这个key的复制行为也是NSDictionary如何工作的基础,但这也有一个限制:你可以只使用Objective-C对象作为
NSDictionary的key,如果它支持NSCopying协议。此外,key应该是小且高效的,以至于复制的时候不会对CPU和内存造成负担。

这意味着,NSDictionary中真的只有适合“value”类型的对象作为key(如简短字符串和数字)。这不是离线的对象到对象的映射模型。

对象到对象的映射

NSMapTable(顾名思义)更适合于一般意义的映射。这取决于它是如何构造的,NSMapTable可以处理的“key-to-object”样式映射的NSDictionary,但它也可以处理“object-to-object”的映射
- 也被称为“associative
array
”或简称为“map”。

例如,一个NSMapTable构造如下:

NSMapTable *keyToObjectMapping =
[NSMapTable
mapTableWithKeyOptions:NSMapTableCopyIn
valueOptions:NSMapTableStrongMemory];

将会和NSMutableDictionary工作得一样一样的,复制其“key”,并retaining它的“object”。

一个纯粹的对象到对象(object-to-object)的映射可以构造如下:

NSMapTable *objectToObjectMapping =
[NSMapTable mapTableWithStrongToStrongObjects];

一个对象到对象(object-to-object)的行为可能以前可以用NSDictionary来模拟,如果所有的key都是一个
NSNumber包含于该映射的源对象的内存地址(不要笑,我见过这种情况),但这些内存地址都是奔波在外,Cocoa中首次提供了一个真正的对象到对象
的映射NSMapTable。

NSMapTable的选项

NSMapTable提供的选项是由三部分组成:一个“memory option”(内存选项),一个“personality
option”和“copy in”标志。你可以为每个部分使用一个选项(如果没有提供一个选项的部分将会使用默认行为),这个部分都是位标志(bit
flag)(二进制 “or” 合并在一起)。

理论上,NSMapTable允许以下选项:

  • NSMapTableStrongMemory (a "memory option")

  • NSMapTableWeakMemory (a "memory option")

  • NSMapTableObjectPointerPersonality (a "personality option")

  • NSMapTableCopyIn (a "copy option")

NSMapTableStrongMemory是默认的“memory option”。然而,默认的“personality
option”,默认“copy in”的行为没有名字那么这两个值可以被视为隐含在列表中。

memory option

Objective-C使用“strong”和“week”作为垃圾回收机制相关的术语,它可能不是很明显,这些选项可以在垃圾回收机制代码之外使用(苹果称它为手动内存管理)。

在垃圾回收机制外,他们被定义为:

  • strong: 使用 retain 和 release

  • weak: 不使用 retain 和 release

NSMapTable只允许NSPointerFunctionsOptions对应的Objective-C对象“personality
option”。还有其他NSPointerFunctionsOptions “personality
option”里的“strong”指针的行为不包括retain和release,但这些选项在NSMapTable都是不允许的。

关于使用垃圾回收机制的“week”之外的警告:

指针将不会被归零如在垃圾回收环境所以你必须要小心,不要取消引用指针,如果它被释放。


Personality options

该NSMapTableObjectPointerPersonality选项用来控制是否isEqualTo:和哈希对象中的方法添加的对象添加到集合时使用。

  • NSMapTableObjectPointerPersonality指定

    对象的指针的值是用于直接比较和位移哈希生成(isEqualTo:和散列方法是不使用)。

  • NSMapTableObjectPointerPersonality 不指定(默认行为)

    的哈希值与isEqualTo:方法会在调用的关键在确定的存储位置NSMapTable。这些方法的返回值不应改变(是不可变)为主要用在时间NSMapTable。

两行为暗示内容实现了NSObject的协议,所以在这个协议方法也可以在key和object调用。特别地,描述的方法可以在被调用NSMapTable包含密钥和对象无论使用的“Personality
options”。该NSMapTable将只支持NSCoding如果所有的key和object实现了NSCoding协议了。

Copy options

如果NSMapTableCopyIn被指定,当NSCopying协议被加入时NSMapTable使用使自己的数据副本。如果不指定此选项(默认行为)将不会复制。


翻译自:NSMapTable: more than an NSDictionary for weak
pointers

这篇文章虽然很久了(2008年),但就算放在当下也是很有学习价值的,感谢Google translate,感谢Baidu
translate!

[转] NSMapTable 不只是一个能放weak指针的 NSDictionary,布布扣,bubuko.com

时间: 2024-12-28 22:26:35

[转] NSMapTable 不只是一个能放weak指针的 NSDictionary的相关文章

while循环操作,输入一个整数放入到变量n中, 如果这个整数大于0,那么计算1+2+3+……+n的结果, 否则输出“输入的数据有错误”。

import java.util.Scanner; /** * @author 蓝色以太 while循环操作,输入一个整数放入到变量n中, 如果这个整数大于0,那么计算1+2+3+--+n的结果, * 否则输出"输入的数据有错误". */ public class While2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("

Objective-C中,ARC下的 strong和weak指针原理解释

Objective-C中,ARC下的 strong和weak指针原理解释 提示:本文中所说的"实例变量"即是"成员变量","局部变量"即是"本地变量" 一.简介 ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理,因为编译器为你处理了一切 注意:ARC 是编译器特性,而不是 iOS 运行时特性(除

ARC - strong和weak指针

ARC指南1 - strong和weak指针 提示:本文中所说的"实例变量"即是"成员变量","局部变量"即是"本地变量" 一.简介 ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理,因为编译器为你处理了一切 注意:ARC 是编译器特性,而不是 iOS 运行时特性(除了weak指针系统),它也不

【转截strong和weak指针

参考文献:  iOS ARC 完全指南 提示:本文中所说的"实例变量"即是"成员变量","局部变量"即是"本地变量" 一.简介 ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理,因为编译器为你处理了一切 注意:ARC 是编译器特性,而不是 iOS 运行时特性(除了weak指针系统),它也不是类似

ARC指南1 - strong和weak指针

一.简介 ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理,因为编译器为你处理了一切 注意:ARC 是编译器特性,而不是 iOS 运行时特性(除了weak指针系统),它也不是类似于其它语言中的垃圾收集器.因此 ARC 和手动内存管理性能是一样的,有时还能更加快速,因为编译器还可以执行某些优化 二.原理 ARC 的规则非常简单:只要还有一个变量指向对象,对象就会保持

strong和weak指针

提示:本文中所说的"实例变量"即是"成员变量","局部变量"即是"本地变量" 一.简介 ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理,因为编译器为你处理了一切 注意:ARC 是编译器特性,而不是 iOS 运行时特性(除了weak指针系统),它也不是类似于其它语言中的垃圾收集器.因此 ARC

关于数组的a和&a的区别:一个是普通的指针,一个是数组的指针

这个问题是我和同学讨论时,产生的思考,后来做的实验性解答. 先来看一段小程序 1. #include<iostream> 2. using namespace std; 3. 4. int main() 5. { 6. int a[5]={1,2,3,4,5}; 7. int *ptr=(int *)(&a+1); 8. cout<<*(a+1)="<<*(a+1)<<"*(ptr-1)="<<*(ptr-1

天下数据教你如何实现一个空间放多个网站

通常一些个人站长或者公司可能同时拥有几个网站.由于其他几个网站流量不高,而每个网站都租用一个虚拟主机空间的话,感觉有点浪费.所以,大家可能会想虚拟主机能不能也像独立服务器那样放置多个网站呢?答案是肯定的.但是,由于每台虚拟主机空间的IIS连接数和CUP占用率非常有限,一般情况下还是不建议在一个虚拟主机内放多个网站.不过,今天既然说到可以实现,那么天下数据就教大家如何使一台虚拟主机放多个网站吧! ①首先建立一个默认主页index.asp 接着把A站放在A文件夹下 B站放在B文件夹下 C站放在C文件

一个控件weak的小解释

因为控件他爹( view.superview )已经揪着它的小辫了( strong reference ),你( viewController )眼瞅着( weak reference )就好了. 当然,如果你想在 view 从 superview 里面 remove 掉之后还继续持有的话,还是要用 strong 的( 你也揪着它的小辫, 这样如果他爹松手了它也跑不了 ).