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 ...
随机推荐
- 在高德地图上用svg.js绘制简单图形
这段时间做的一个项目,需要在地图上绘制简单的图形.在学习高德地图JS API的过程中,发现高德地图提供的点.线等API并不能满足我的需求,还好它开放了自定义图层CustomLayer,官方说自定义图层 ...
- 前端每日实战:4# 视频演示如何用纯 CSS 创作一个金属光泽 3D 按钮特效
效果预览 按下右侧的"点击预览"按钮在当前页面预览,点击链接全屏预览. https://codepen.io/zhang-ou/full/MGeRRO 可交互视频教程 此视频是可以 ...
- redis系列之------过期策略
前言 我们都知道redis是常驻在内存当中的,因此他的效率比MySQL要快很多很多.但又引发了另外一个问题,内存从本质上讲,它是昂贵的,不能用于大量的长时间的存储,他是“不安全不稳定的“,并且有可能存 ...
- ysoserial源码结构分析
1.前言 之前也花了几天晚上熟悉了一下commonscollections系列的构造,那么学习一下这个项目是如何设计的也挺重要,多学习大佬如何写代码应该也能对自己的代码能力有提升吧~2333 2.项目 ...
- AlphaGo、人工智能、深度学习解读以及应用
经过比拼,AlphaGo最终还是胜出,创造了人机大战历史上的一个新的里程碑.几乎所有的人都在谈论这件事情,这使得把“人工智能”.“深度学习”的热潮推向了新的一个高潮.AlphaGo就像科幻电影里具有人 ...
- 17-Java-文件上传报错(commons-fileupload包和commons-io包不支持JDK版本:UnsupportedClassVersionError: org/apache/commons/io/IOUtils : Unsupported major.minor version 52.0)
文件上传报错(commons-fileupload包和commons-io包不支持JDK版本) 这个bug可把我弄惨了!!!我代码是想通过写个文件上传,我写的文件上传需要用到commons-fileu ...
- python学习-练习题9*9乘法表巩固
9*9乘法表 分析: 1X1为一行 1X2 2X2 为一行 for i in range(1,10): for j in range(1,i+1): print(str(i) + 'X' + str( ...
- 如何从普通程序员晋升为架构师 面向过程编程OP和面向编程OO
引言 计算机科学是一门应用科学,它的知识体系是典型的倒三角结构,所用的基础知识并不多,只是随着应用领域和方向的不同,产生了很多的分支,所以说编程并不是一件很困难的事情,一个高中生经过特定的训练就可以做 ...
- DOM解读
DOM解读 DOM概念 - document object model:文档对象模型 操作文档的一套方法,document是一个对象,是dom的顶级对象,属于window的一个对象,并且可以说是最出色 ...
- 提示消息无缝向上滚动(vue)
<div class="order-tips__message-item" :class="getClass(index)" v-for="(o ...