NSHashtable and NSMaptable

NSSet, NSDictionary, NSArray是Foundation框架关于集合操作的常用类, 和其他标准的集合操作库不同, 他们的实现方法对开发者进行隐藏, 只允许开发者写一些简单的代码,让他们相信这些代码有理由正常的工作.。

然而这样的话最好的代码抽象风格就会被打破,苹果的本意也被曲解了. 在这种情况下, 开发者寻求更好的抽象方式来使用集合,或者说寻找一种更通用的方式。

对于 NSSet 和 NSDictionary,打破代码抽象风格的是他们在内存中存取object的方式. 在NSSet中, objects 是被强引用的(strongly referenced), 同样NSDictionary中的keys和values也会被NSDictionary复制。如果一个开发者想要存储一个weak类型的值或者使用一个 没有实现NSCopying协议的object作为NSDictionary的key,他可能会很聪明的想到NSValue +valueWithNonretainedObject。 iOS6和OSX 10.5以后,可以分别使用和 NSSet, NSDictionary 地位相同的 NSHashTable,NSMapTable。

这两个类在Foundation的collection中不常用到,为了避免你慌乱无措,下面将介绍这两个类的用法。

NSHashTable

NSHashTable是更广泛意义的NSSet,区别于NSSet / NSMutableSet,NSHashTable有如下特性:

* NSSet / NSMutableSet是对其成员的强类型引用,这些成员被通过hash方法和isEqual方法来完成哈希和对比功能

* NSHashTable是可变的

* NSHashTable可以持有weak类型的成员变量

* NSHashTable可以在添加成员变量的时候复制成员

* NSHashTable可以随意的存储指针并且利用指针的唯一性来进行hash同一性检查(检查成员变量是否有重复)和对比操作(equal),用法如下:

    NSHashTable *hashTable = [NSHashTable hashTableWithOptions:NSPointerFunctionsCopyIn];
    [hashTable addObject:@"foo"];
    [hashTable addObject:@"bar"];
    [hashTable addObject:@42];
    [hashTable removeObject:@"bar"];
    NSLog(@"Members: %@", [hashTable allObjects]); 

NSHashTable是根据一个option参数来进行初始化的,因为从OSX平台上移植到iOS平台上,原来OSX平台上使用的枚举类型被放弃了,从而用option来代替,命名也发生了一些变化:

NSHashTableStrongMemory: 等同于NSPointerFunctionsStrongMemory. 对成员变量进行强引用。这是一个默认值。如果采用这个默认值,NSHashTable和NSSet就没什么区别了。

NSHashTableWeakMemory: 等同于NSPointerFunctionsWeakMemory.对成员变量进行弱引用. 使用 NSPointerFunctionsWeakMemory, object 引用在最后释放的时候会被指向 NULL。

NSHashTableZeroingWeakMemory: 已被抛弃.使用NSHashTableWeakMemory 代替。

NSHashTableCopyIn: 在对象被加入集合之前进行复制 (NSPointerFunction -acquireFunction). 等同于NSPointerFunctionsCopyIn。

NSHashTableObjectPointerPersonality: 用指针来等同代替实际的值,当打印这个指针的时候相当于调用description方法。和NSPointerFunctionsObjectPointerPersonality等同。

NSMapTable

NSMapTable是对更广泛意义的NSDictionary。和NSDictionary / NSMutableDictionary相比具有如下特性:

* NSDictionary / NSMutableDictionary会复制keys并且通过强引用values来实现存储。

* NSMapTable是可变的。

* NSMapTable可以通过弱引用来持有keys和values,所以当key或者value被deallocated的时候,所存储的实体也会被移除。

* NSMapTable可以在添加value的时候对value进行复制

和NSHashTable类似,NSMapTable可以随意的存储指针,并且利用指针的唯一性来进行对比和重复检查。

用法:假设用NSMapTable来存储不用被复制的keys和被若引用的value,这里的value就是某个delegate或者一种弱类型。

    id delegate = ...;
    NSMapTable *mapTable = [NSMapTable mapTableWithKeyOptions:NSMapTableStrongMemory
                                                 valueOptions:NSMapTableWeakMemory];
    [mapTable setObject:delegate forKey:@"foo"];
    NSLog(@"Keys: %@", [[mapTable keyEnumerator] allObjects]);
    和NSHashTable类似,NSMapTable 也是根据一个option来初始化的。
    NSMapTableStrongMemory
    NSMapTableWeakMemory
    NSHashTableZeroingWeakMemory
    NSMapTableCopyIn
    NSMapTableObjectPointerPersonality
    Subscripting 

看完上面几个小例子后,你可能会想 “为什么不使用object subscripting呢?”。一些激进的NSHipster估计已经开始动手写NSMapTable的subscripting category了。

那么为什么NSMapTable不能继承subscripting?

来看看下面的代码:

@implementation NSMapTable (NSHipsterSubscripting)

- (id)objectForKeyedSubscript:(id)key
{
    return [self objectForKey:key];
}

- (void)setObject:(id)obj forKeyedSubscript:(id)key
{
    if (obj != nil) {
        [self setObject:obj forKey:key];
    } else {
        [self removeObjectForKey:key];
    }
}

@end

注意:参数key是类型的。这对NSDictionary NSMutableDictionary来讲是非常有用的,但是我们不能臆断对NSMapTable也同样适用。我们陷入一个僵局:通过id ,我们不能利用NSMapTable实现subscripting。如果object subscripting 的代理方法放弃了 约束,那么使用NSMutableDictionary -setObject:forKeyedSubscript:的时候编译将得不到想要的结果。

所以说实话,对比NSMapTable所处的位置,句法的方便和快捷并不是大数人所关注的。

通常,记住编程不是为了让人更聪明,而是最大化抽象一个问题的能力。 NSSet and NSDictionary是非常伟大的类,他们能解决99%的问题,也无疑是用来工作的正确工具。如果,然而你的问题牵扯到上述的内存问题时候, NSHashTable 和 NSMapTable 是值得一看的。

本文转自Nidom的博客,原文:《NSHashtable & NSMaptable

http://www.cocoachina.com/industry/20140605/8683.html

时间: 2024-10-23 05:47:23

NSHashtable and NSMaptable的相关文章

NSHashTable 和 NSMapTable的学习

今天在实现play gif功能的时候,看到有两个类比较陌生,就在此记录下看到的东西: NSSet和NSDictionary是两个常用的类,但是他们默认假定了其中对象的内存行为.对于NSSet,object是强引用的,和NSDictionary中的value是一样的.而NSDictionary中的key则是copy的,因此当开发者想要使NSSet的objects或者NSDictionary的values为weak,或者NSDictionary使用没有实现协议的对象作为key时,比较麻烦(需要使用N

NSHashTable 和 NSMapTable学习

今天,在实现play gif时间功能,我看见两个陌生班,只需看看这个纪录: NSSet和NSDictionary是两个经常使用的类,可是他们默认假定了当中对象的内存行为.对于NSSet.object是强引用的,和NSDictionary中的value是一样的.而NSDictionary中的key则是copy的,因此当开发人员想要使NSSet的objects或者NSDictionary的values为weak,或者NSDictionary使用没有实现协议的对象作为key时,比較麻烦(须要使用NSV

iOS7: 漫谈基础集合类(NSArray,NSSet,NSOrderedSet,NSDictionary,NSMapTable,NSHashTable, NSPointerArray, NSIndexSet,NSCache, NSFastEnumeration)

基础集合类是每一个Mac/iOS应用的基本组成部分.在本文中,我们将对”老类”(NSArray, NSSet)和”新类”(NSMapTable, NSHashTable, NSPointerArray)进行一个深入的研究,探索每一个的效率细节,并讨论其使用场景. 提示:本文包含一些参照结果,但它们并不意味着绝对精确,也没有进行多个.复杂的测试.这些结果的目的是给出一个快速和主要的运行时统计.所有的测试基于iPhone 5s,使用Xcode 5.1b1和iOS 7.1b1,64位的程序.编译选项设

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

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

iOS -copy&mutableCopy

1.对于非容器对象(NSString) 不可变 (NSString) copy :浅复制,指针指向 mutableCopy:深复制,生成可变字符串对象 可变(NSMutableString) copy: 深复制,生成不可变字符串对象 mutableCopy :深复制,生成可变字符串对象 2.对于容器类对象 数组 不可变(NSArray) copy :浅复制,指针指向 mutableCopy:深复制,生成可变数组对象(但,数组中的对象没有进行处理的话,数组的中的对象是浅复制) 可变(NSMutab

[iOS翻译]《iOS 7 Programming Pushing the Limits》系列:你可能不知道的Objective-C技巧

简介: 如果你阅读这本书,你可能已经牢牢掌握iOS开发的基础,但这里有一些小特点和实践是许多开发者并不熟悉的,甚至有数年经验的开发者也是.在这一章里,你会学到一些很重要的开发技巧,但这仍远远不够,你还需要积累更多的实践来让你的代码更强力. /* 本文翻译自<iOS 7 Programming Pushing the Limits>一书的第三章“You May Not Know”,想体会原文精髓的朋友请支持原书正版. ——————(博客园.新浪微博)葛布林大帝 */ 目录: 一. 最好的命名实践

[转][iOS]NSHash?Table &amp; NSMap?Table

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 (reasonabl

NSMapTable、NSHashTable与NSPointerArray的封装

说明 NSMapTable对应NSDictionary:NSHashTable对应NSSet:NSPointerArray对应NSArray,本人通过装饰设计模式对他们的使用进行了封装. 源码 https://github.com/YouXianMing/WeakList // // WeakDictionary.h // IteratorPattern // // Created by YouXianMing on 15/9/12. // Copyright (c) 2015年 YouXian

Cocoa 集合类型:NSPointerArray,NSMapTable,NSHashTable

iOS 中有很多种集合类型,最为常见的可能就 NSArray.NSDictionary.NSSet,但其实还有 NSPointerArray.NSMapTable.NSHashTable 等类型,虽然后面三个类型不常见,但是它们能在关键时刻,「救你一命」. 环境信息macOS 10.12.1Xcode 8.2iOS 10.2 先来看看传统的集合类型都有哪些短板: 放到集合中的对象,只能强引用 如果想要弱引用,要先用 NSValue 打包 不能放入 nil 而对于 NSPointerArray.N