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 ...
随机推荐
- mysql中用SQL增加、删除字段,修改字段名
CREATE TABLE `tuser` ( `id` int(11) NOT NULL, `name` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) ) ...
- 【WPF学习】第五十四章 关键帧动画
到目前为止,看到的所有动画都使用线性插值从起点到终点.但如果需要创建具有多个分段的动画和不规则移动的动画.例如,可能希望创建一个动画,快速地将一个元素滑入到视图中,然后慢慢地将它移到正确位置.可通过创 ...
- MySQL集群MGR架构for单主模式
本文转载自: https://www.93bok.com MGR简介 MySQL Group Replication(简称MGR)是MySQL官方于2016年12月推出的一个全新的高可用与高扩展的解决 ...
- 处理 Vue 单页面 SEO 的另一种思路
vue-meta-info 官方地址: https://github.com/monkeyWang... (设置vue 单页面meta info信息,如果需要单页面SEO,可以和 prerender- ...
- PhaserJS 3 屏幕适配时的小坑 -- JavaScript Html5 游戏开发
巨坑:在config内不要把 width 设为 window.innnerWidth在config内不要把 width 设为 window.innnerWidth在config内不要把 width 设 ...
- vue+element tree(树形控件)组件(1)
最近做了第一个组内可以使用的组件,虽然是最简版,也废了不少力.各位前辈帮我解决问题,才勉强搞定.让我来记录这个树形组件的编写过程和期间用到的知识点. 首先说说需求,就是点击出现弹窗+蒙板,弹窗内容是一 ...
- 日常破解--从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库
一.题目来源 题目来源:XCTF app3题目 二.解题过程 1.下载好题目,下载完后发现是.ab后缀名的文件,如下图所示: 2.什么是.ab文件?.ab后缀名的文件是Andr ...
- MySQL敏感数据加密及解密
大数据时代的到来,数据成为企业最重要的资产之一,数据加密的也是保护数据资产的重要手段.本文主要在结合学习通过MySQL函数及Python加密方法来演示数据加密的一些简单方式. 1. 准备工作 为了便于 ...
- 一,kubeadm初始化k8s集群
docker安装 wget https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo yum inst ...
- CSS 权重图
关系图 图片出处我找不到了. 结论 权重从高到低排序 1. !important 2. style 3. #id 4. .class .child-class 5. .class1.class2 6. ...