NSArray、NSDictionary
一、NSDictionary
1.1 使用自定义对象 key
Dictionaries manage pairs of keys and values. A key-value pair within a dictionary is called an entry. Each entry consists of one object that represents the key, and a second object which is that key’s value. Within a dictionary, the keys are unique—that is, no two keys in a single dictionary are equal (as determined by isEqual:). A key can be any object that adopts the NSCopying protocol and implements the hash and isEqual: methods.
字典管理着键值对。键是唯一的,同一个字典里面不会有相同的 key(由 isEqual: 确定),key 可以是遵守 NSCoping 协议并实现 hash 和 isEqual: 方法的任何对象。
- (instancetype)copyWithZone:(NSZone *)zone
{
return self;
}

如果字典很少更改或大量更改,则应使用不可变的字典;否则使用可变字典。
Objects added as values to a dictionary are not copied (unless you pass YES as the argument to initWithDictionary:copyItems:). Rather, a strong reference to the object is added to the dictionary.
作为 value 添加到字典的对象不会被复制(除非调用 initWithDictionary:copyItems: 方法,并且参数传递 YES),而是将对对象的强引用添加到字典中。Copying Collections
You can also add entries from another dictionary using the addEntriesFromDictionary: instance method. If both dictionaries contain the same key, the receiver’s previous value object for that key is released and the new object takes its place.
使用 addEntriesFromDictionary: 从一个已有的字典添加键值对时,相同 key 对应的 value 会被替换。
Keys must conform to the NSCopying protocol. Methods that add entries to dictionaries—whether as part of initialization (for all dictionaries) or during modification (for mutable dictionaries)— don’t add each key object to the dictionary directly. Instead, they copy each key argument and add the copy to the dictionary. After being copied into the dictionary, the dictionary-owned copies of the keys should not be modified.
Keys must implement the hash and isEqual: methods because a dictionary uses a hash table to organize its storage and to quickly access contained objects. In addition, performance in a dictionary is heavily dependent on the hash function used. With a bad hash function, the decrease in performance can be severe. For more information on the hash and isEqual: methods see NSObject.
使用自定义对象 key 时,对象需要遵守 NSCoping 协议,存储数据时,字典会持有 key 的复制,复制到字典中后,不应修改字典拥有的键的副本。
键必须实现 hash 和 isEqual: 方法,因为字典使用哈希表来组织其存储并快速访问所包含的对象。此外,字典的性能在很大程度上取决于所使用的哈希函数。如果哈希函数不正确,性能下降可能会很严重。
注意:不要使用一个很大的对象作为 key,例如 NSImage 对象,这样会导致性能下降。
1.2 NSMapTable
NSMapTable 允许针对特定情况(例如,当您需要高级内存管理选项时或想要保留特定类型的指针时)定制其他的存储选项。如图中的映射表配置为保存对其值对象的弱引用。

还可以指定是否要复制输入到数组中的对象。
The NSMapTable class also defines a number of convenience constructors for creating a map table with strong or weak references to its contents. For example, mapTableWithStrongToWeakObjects creates a map table that holds strong references to its keys and weak references to its values. These convenience constructors should only be used if you are storing objects.
使用 mapTableWithStrongToWeakObjects 可以强引用 key,弱引用 value。
为了能够使用任意的指针,请同时使用 NSPointerFunctionsOpaqueMemory 和 NSPointerFunctionsOpaquePersonality 值选项对其进行初始化。键和值的 options 不必相同。当使用映射表包含任意指针时,指针类型应该使用 c 语言的 void *。
NSPointerFunctionsOptions keyOptions = NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPersonality | NSPointerFunctionsCopyIn;
NSPointerFunctionsOptions valueOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality;
NSMapTable * mapTable = [NSMapTable mapTableWithKeyOptions:keyOptions valueOptions:valueOptions];
int i = 1;
NSString * key = @"Key";
NSMapInsert(mapTable, key, &i);
NSLog(@"Key contains: %i", *(int *) NSMapGet(mapTable, key));
1.3 底层原理
Objective-C 中的字典 NSDictionary 底层其实是一个哈希表。
NSDictionary 使用 hash 表来实现 key 和 value 之间的映射和存储,hash 函数设计的好坏影响着数据的查找访问效率。数据在 hash 表中分布的越均匀,其访问效率越高。而在 Objective-C 中,通常都是利用 NSString 来作为键值,其内部使用的 hash 函数也是通过使用 NSString 对象作为键值来保证数据的各个节点在 hash 表中均匀分布。
字典每个条目存取是通过将字典的键(Key)计算出键的 hash 值,通过查 hash 表获取具体的 value。所以作为 NSDictionary 的键(Key)取值的时候,只要其 key 对象内容地址相同就可以取出相应的值。
二、数组
2.1 NSPointArray
NSPointArray 类似 NSMutableArray,但它可以容纳 nil 值,同 count 值也包含 nil 的数量。它还允许你在定制特定的情况下设置额外的存储选项。
NSPointerArray * arr = [NSPointerArray pointerArrayWithOptions:NSPointerFunctionsStrongMemory];
[arr addPointer:nil];
[arr addPointer:@"sss"];
NSLog(@"%lu", arr.count);
NSLog(@"%@", [arr pointerAtIndex:0]);
NSLog(@"%@", [arr pointerAtIndex:1]);
arr.count = 1;
NSLog(@"%@", [arr pointerAtIndex:0]);
NSLog(@"%@", [arr pointerAtIndex:1]); // 崩溃。-[NSConcretePointerArray pointerAtIndex:]: attempt to access pointer at index 1 beyond bounds 1'

当您想要使用弱引用的有序集合时,可以使用 NSPointerArray 对象。例如,假设您有一个包含一些对象的全局数组。因为从不收集全局对象,所以除非将其保持为弱状态,否则不能释放其所有内容。配置为弱保存对象的指针数组不拥有其内容。如果在此类指针数组中没有对对象的强引用,则可以释放这些对象。
为了使用任意的指针,可以同时使用 NSPointerFunctionsOpaqueMemory 和NSPointerFunctionsOpaquePersonality 选项对其进行初始化。
NSPointerFunctionsOptions options = (NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality);
NSPointerArray * ptrArray = [NSPointerArray pointerArrayWithOptions:options];
int i = 1;
[ptrArray addPointer:&i];
NSLog(@" Index 0 contains: %i", *(int *)[ptrArray pointerAtIndex:0]);
三、数据拷贝
The normal copy is a shallow copy that produces a new collection that shares ownership of the objects with the original. Deep copies create new objects from the originals and add those to the new collection.
通常情况是浅拷贝,它会生成一个新集合,该集合与原始对象共享对象的所有权。深拷贝从原始对象创建新对象,并将其添加到新集合中。

When you create a shallow copy, the objects in the original collection are sent a retain message and the pointers are copied to the new collection.
浅拷贝时,原始数据集合中的对象会发送 retain 消息,并将指针拷贝到新数据集合中。
You can use the collection’s equivalent of initWithArray:copyItems: with YES as the second parameter. If you create a deep copy of a collection in this way, each object in the collection is sent a copyWithZone: message. If the objects in the collection have adopted the NSCopying protocol, the objects are deeply copied to the new collection, which is then the sole owner of the copied objects. If the objects do not adopt the NSCopying protocol, attempting to copy them in such a way results in a runtime error. However, copyWithZone: produces a shallow copy. This kind of copy is only capable of producing a one-level-deep copy.
使用 copyItem:YES 方法时,会给集合中的每个对象发送 copyWithZone: 消息。如果对象实现了 NSCopying 协议,那么这些对象会被深拷贝到新的数据集合;如果没有实现协议,则会导致运行时错误。
然而 copyWithZone: 生成的是浅层的“深拷贝”,只是做了一层的深拷贝,如果数据是多层数组嵌套的话,则第二层、第三层...的数据没有进行深拷贝。
If you need a true deep copy, such as when you have an array of arrays, you can archive and then unarchive the collection, provided the contents all conform to the NSCoding protocol.
如果想真正的深拷贝,只要内容全部符合 NSCoding 协议,则可以存档然后取消存档该集合。
NSArray * trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
[NSKeyedArchiver archivedDataWithRootObjectoldArray]];
复制集合时,该集合或其包含的对象的可变性可能会受到影响。
copyWithZone: makes the surface level immutable. All deeper levels have the mutability they previously had. 第一层是可变的,其余深层还是以前的可变性。
initWithArray:copyItems: with NO as the second parameter gives the surface level the mutability of the class it is allocated as. All deeper levels have the mutability they previously had. 第一层保持分配时的可变性,其余深层还是以前的可变性
initWithArray:copyItems: with YES as the second parameter gives the surface level the mutability of the class it is allocated as. The next level is immutable, and all deeper levels have the mutability they previously had.
Archiving and unarchiving the collection leaves the mutability of all levels as it was before. 第一层保持分配时的可变性,第二层是可变的,其余深层还是以前的可变性

四、文章
Dictionaries: Collections of Keys and Values
NSArray、NSDictionary的更多相关文章
- Foundation框架之NSArray、NSDictionary、NSSet及其Mutable类型
Foundation框架之NSArray.NSDictionary.NSSet及其Mutable类型 目录 概述——对Foundation框架集合类的理解 NSArray NSDictionary N ...
- iOS 将NSArray、NSDictionary转换为JSON格式进行网络传输
http://blog.csdn.net/worldzhy/article/details/49982491 将NSArray.NSDictionary转换为JSON格式进行网络传输,是经常用到的,但 ...
- 在Objective-C 中使用字符生成NSArray、NSDictionary、NSNumber
@符号不仅可以生成字符串,还可以生成其他数据类型如NSArray.NSDictionary和NSNumber,是一种简洁快速的用法. // NSArray array = [NSArray array ...
- OC 解决NSArray、NSDictionary直接打印中文出现乱码的问题
在iOS开发中,经常需要查看数组中得元素是否是自己想要的,但是苹果并没有对直接打印数组中得中文作处理,直接打印就会出现一堆很讨厌的东西,解决其实很简单,就是需要通过为NSArray添加分类,重写 - ...
- NSString、NSArray、NSDictionary和NSData的数据存储
#import "ViewController.h" @interface ViewController () @end @implementation ViewControlle ...
- 放在NSArray、NSDictionary等容器内的对象Item,Item中的property在程序运行过程中被无故释放
可能是被释放的property本身是OC对象而它的属性被误写成assign,例如: @interface MyItem : Object @property (nonatomic, assign) N ...
- 用@property声明的NSString(或NSArray,NSDictionary)经常使用copy关键字,为什么?如果改用strong关键字,可能造成什么问题?
因为父类指针可以指向子类对象,使用 copy 的目的是为了让本对象的属性不受外界影响,使用 copy 无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本. 如果我们使用是 str ...
- 04-Foundation-NSSet、NSDictionary、block
目录: 一.NSSet集合 二.NSDictionary字典 三.block代码块 回到顶部 一.NSSet集合 1 NSSet是一个无序的,管理对个对象的集合类,最大特点是集合中不允许出现重复对象, ...
- iOS-NSBundle、NSArray、NSDictionay
NSBundle.NSArray.NSDictionay 读取plist文件 NSDictionary *dict= [NSDictionary dictionaryWithContentsOfFi ...
随机推荐
- Roma - Facebook工具链大一统
什么是roma roma,中文名罗马,是Facebook的rn团队的产出,是一个试验性质的javascript工具链,集编译,linter,格式化,打包,测试等等于一体.目标是成为一个处理javasc ...
- vue——一个页面实现音乐播放器
请忽略下面这段文字年关将至,时间好歹又多出了些许.却不敢过度消遣.岁月未曾饶过我,我亦不想饶过岁月.且将它塞得膨胀,让这一年看似加更充实.不曾料想我一个爱些风花雪月.研墨行歌之人,却做起了碼农这一行当 ...
- 2017、2018面试分享(js面试题记录)记得点赞分享哦;让更多的人看到~~
2017面试分享(js面试题记录) 1. 最简单的一道题 '11' * 2 'a8' * 3 var a = 2, b = 3; var c = a+++b; // c = 5 2. 一道this的问 ...
- 在windows上极简安装GPU版AI框架(Tensorflow、Pytorch)
在windows上极简安装GPU版AI框架 如果我们想在windows系统上安装GPU版本的AI框架,比如GPU版本的tesnorflow,通常我们会看到类似下面的安装教程 官方版本 安装CUDA 安 ...
- 基于 Redis 实现 CAS 操作
基于 Redis 实现 CAS 操作 Intro 在 .NET 里并发情况下我们可以使用 Interlocked.CompareExchange 来实现 CAS (Compare And Swap) ...
- OpenGL 实现视频编辑中的转场效果
转场介绍 转场效果是什么? 转场效果,简单来说就是两段视频之间的衔接过渡效果. 现在拍摄 vlog 的玩家越来越多,要是视频没有一两个炫酷的转场效果,都不好意思拿出来炫酷了. 那么如何在视频编辑软件中 ...
- div隐藏滚动条,仍可滚动
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...
- 【Oracle】RAC的多实例数据迁移至单机的多实例。
思路:一般的思路可以通过RMAN进行数据的恢复.由于数据库可以停机,因此,这次试用数据泵(expdp,impdp)进行数据 的导入导出. 1.源数据库导出 通过编写导出shell脚本导出数据,如下: ...
- 5G 将带给程序员哪些新机会呢?
5G,第 5 代移动通信技术,华为在此领域远远领先同行,这也让它成了中美贸易战的最前线.我的第一份工作就在通信行业,当时电信标准都在欧美企业手里,国内企业主要是遵照标准研发软硬件设备,核心芯片靠进口. ...
- (转)const的内部链接属性(C++中适用)
转载自:http://xiangwangfeng.com/2011/05/02/const%E7%9A%84%E5%86%85%E9%83%A8%E9%93%BE%E6%8E%A5%E5%B1%9E% ...