惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
Martin Fowler
Martin Fowler
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Stack Overflow Blog
Stack Overflow Blog
C
Check Point Blog
阮一峰的网络日志
阮一峰的网络日志
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
B
Blog
O
OpenAI News
云风的 BLOG
云风的 BLOG
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
L
LangChain Blog
V
Vulnerabilities – Threatpost
P
Privacy & Cybersecurity Law Blog
Microsoft Azure Blog
Microsoft Azure Blog
H
Help Net Security
博客园 - 三生石上(FineUI控件)
C
Cyber Attacks, Cyber Crime and Cyber Security
N
News | PayPal Newsroom
The Register - Security
The Register - Security
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
T
Threat Research - Cisco Blogs
C
Cisco Blogs
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Vercel News
Vercel News
宝玉的分享
宝玉的分享
T
Tailwind CSS Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Attack and Defense Labs
Attack and Defense Labs
人人都是产品经理
人人都是产品经理
S
Security Affairs
爱范儿
爱范儿
Engineering at Meta
Engineering at Meta
T
Tor Project blog
大猫的无限游戏
大猫的无限游戏
L
Lohrmann on Cybersecurity
aimingoo的专栏
aimingoo的专栏
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 【当耐特】
V
V2EX
V
Visual Studio Blog
The GitHub Blog
The GitHub Blog
雷峰网
雷峰网
WordPress大学
WordPress大学
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
L
LINUX DO - 最新话题
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Schneier on Security
Schneier on Security
小众软件
小众软件
PCI Perspectives
PCI Perspectives

isaced

使用 TypeScript 构建的 appstore-connect-sdk 归档 我用 SwiftUI 写了一个 V2ex 客户端 Docker 容器化多应用部署 Swift Server-side SDWebImage 为什么无法读取 webpmux 生成的 WebP 动图? [译] 探索 Swift 4 中新的 String API 对一个 Django 站点做 ab 压力测试 fir-mac 开发笔记 iOS10 Safari 引导用户信任企业签名 Swift Web 开发之 Vapor - 模版 Leaf(三) Swift Web 开发之 Vapor - 路由(二) HoloLens 初体验 Swift Web 开发之 Vapor - 入门(一) Jenkins for iOS 搭建日记 iOS HOOK 注入与重签名 Xcode 使用 Configuration 来配置不同的项目环境 图床从SAE迁移到七牛 给 UIProgressView 脱掉那层微弱的渐变 初用 CocoaAsyncSocket 记一次 SQLite 性能优化 有多色 - 开发小记 海岛风情 - 泰国普吉岛六日游 EGOCache 源码解析 日语五十音假名临摹校验算法 [iOS] UITextView 追加文字自动跳到顶部解决方法 Cocoa 新的依赖管理工具:Carthage 新年快乐! 博客主机换到搬瓦工 写了个iOS小游戏:有多色 iOS 后台任务之 Long-running background task 悄悄的就必须用 XCode 5.1.1 上传了! HTTP Content-type 与 AFNetworking Objective-Cloud 初体验(1) 掌中站上架小记 NSLoger 上线了 Python Markdown 做语法限制 Nginx + Gunicorn + Django 部署小记 用Shell脚本批量裁剪App Icon各个尺寸 LaunchRocket使用小记 用宏提速NSCoding 2014新年伊始:近期读过的好文推荐 [iOS] stringWithFormat 和 initWithFormat 有何不同? Apache + Flask + mod_wsgi + Koding 部署小记 收集几个Objective-C的HTML解析库 2013,再见! Emlog到Typecho的迁移工具:emlog2typecho [iOS]给上拉下拉刷新PullToRefresh做本地化 [iOS]代码推荐:大图缩放视图 - Vertigo iOS:hidesBottomBarWhenPushed的正确用法 Xcode 5新的Interface Builder,你准备好了吗? [翻译]如何使用Django创建简单的博客 我的Mac音乐播放器 初识 NSDataDetector Objective-C 计算代码运行时间 WordPress上传文件自动重命名 iOS:仿jing.fm的音乐播放视图 我的啃黑苹果之路 关于 搜索 项目
NSMapTable: 不只是一个能放weak指针的 NSDictionary
2014-01-14 · via isaced

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

Leopard 中其他 Cocoa API

Cocoa 增加了几个新的集合类类型在 Mac OS X 10.5(Leopard):

NSPointerArray 是全新的,但大部分如 NSHashTableNSMapTable 的功能之前可从 Foundation 中看到影子。

在某些方面,这些新的类型,像 NSMutableArrayNSMutableSetNSMutableDictionary 一样,但是给了你使用 week 指针来使用垃圾回收的选择。如果您使用的 Objective-C 2.0 的垃圾回收机制,你应该知道什么是 week 指针,所以使用它的好处是很明显的。

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

虽然在一般意义上,NSPointerArrayNSHashTable 被设计为可以替换 NSMutableArray and NSMutableSet 的角色(有序和无序集合)。 但 NSMapTable 则不同,因为它可以补充 NSMutableDictionary 不能(或不应该)做的事情。

NSDictionary 的局限性

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

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

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

这意味着,NSDictionary 中真的只适合将值类型的对象作为 key(如简短字符串和数字)。并不适合自己的模型类来做对象到对象的映射。

对象到对象的映射

NSMapTable(顾名思义)更适合于一般来说的映射概念。这取决于它的设计方式,NSMapTable 可以处理的 key -> obj 式映射如 NSDictionary,但它也可以处理 obj -> obj 的映射 - 也被称为 “关联数组” 或简称为 “map”。

比如一个 NSMapTable 的构造如下:

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

这将会和 NSMutableDictionary 用起来一样一样的,复制 key,并对它的 object 引用计数 +1。

一个真正的对象到对象(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:hash 方法。

  • NSMapTableObjectPointerPersonality 指定 对象的指针的值是用于直接比较和位移哈希生成(isEqualTo:且不用 hash 方法)。
  • NSMapTableObjectPointerPersonality 不指定(默认行为) hashisEqualTo: 方法将在 key 上调用以确定 NSMapTable 中的存储位置。 这些方法的返回值在 NSMapTable 中使用密钥的持续时间不应该改变(不可变)。

这两种行为都意味着内容实现了 NSObject 协议,因此该协议中的方法也可以在 keyobj 上被调用。 并且可以在 NSMapTable 包含的 key 和对象上调用描述方法,而不管所使用的选项如何。 如果所有的密钥和对象都实现了 NSCoding 协议,NSMapTable 只支持 NSCoding。

Copy options

如果指定了 NSMapTableCopyIn,则 NSMapTable 在添加时使用 NSCopying 协议创建自己的数据副本。 如果不指定此选项(默认行为),则不会复制。


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

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

修订:2017.3.23