iOS之NSArray类簇简介-(copy、mutableCopy导致程序crash)
1、前言
开发时常常用数组对数据进行处理,对NSMutableArray进行操作时经常导致程序崩溃,特研究一下NSArray的类簇!涉及__NSPlaceholderArray、__NSArray0、__NSSingleObjectArrayI、__NSArrayI、__NSArrayM相关类。
2、分析NSArray
2.1、创建不可变出租
NSArray *placeholder = [NSArray alloc];
NSArray *arr1 = [placeholder init];
NSArray *arr2 = [placeholder initWithObjects:@, nil];
NSArray *arr3 = [placeholder initWithObjects:@, @, nil];
NSLog(@"arr: %s", object_getClassName([NSArray array])); // arr: __NSArray0
NSLog(@"placeholder: %s", object_getClassName(placeholder)); // placeholder: __NSPlaceholderArray
NSLog(@"arr1: %s", object_getClassName(arr1)); // arr1: __NSArray0
NSLog(@"arr2: %s", object_getClassName(arr2)); // arr2: __NSSingleObjectArrayI
NSLog(@"arr3: %s", object_getClassName(arr3)); // arr3: __NSArrayI
可以看出 [NSArray array] 等同于[ [NSArray alloc] init],都是空元素类 __NSArray0;
__NSPlaceholderArray:alloc时的对象先统一为这个类对象,不可变数组也是这样;
__NSArray0:数组init后没有元素;
__NSSingleObjectArrayI:数组只有一个元素;
__NSArrayI:不可变数组切元素在一个以上;
2.2、分别对arr1、arr2、arr3进行copy和mutableCopy操作:
NSLog(@"arr1: %s", object_getClassName([arr1 copy])); // arr1: __NSArray0
NSLog(@"arr2: %s", object_getClassName([arr2 copy])); // arr2: __NSSingleObjectArrayI
NSLog(@"arr3: %s", object_getClassName([arr3 copy])); // arr3: __NSArrayI
NSLog(@"=================");
NSLog(@"arr1: %s", object_getClassName([arr1 mutableCopy])); // arr1: __NSArrayM
NSLog(@"arr2: %s", object_getClassName([arr2 mutableCopy])); // arr2: __NSArrayM
NSLog(@"arr3: %s", object_getClassName([arr3 mutableCopy])); // arr3: __NSArrayM
对不可变数组进行copy不会改变类名,但mutableCopy都会变成可变数组;
3、分析NSMutableArray
3.1、创建不可变数组
NSMutableArray *arr = [NSMutableArray alloc];
NSMutableArray *arr1 =[arr init];
NSMutableArray *arr2 = [arr initWithObjects:@, nil];
NSMutableArray *arr3 = [arr initWithObjects:@, @, nil];
NSMutableArray *arr4 = [arr initWithObjects:@, @, @, nil];
NSLog(@"arr: %s", object_getClassName([NSMutableArray array])); // arr: __NSArrayM
NSLog(@"placeholder: %s", object_getClassName(arr)); // placeholder: __NSPlaceholderArray
NSLog(@"arr1: %s", object_getClassName(arr1)); // arr1: __NSArrayM
NSLog(@"arr2: %s", object_getClassName(arr2)); // arr2: __NSArrayM
NSLog(@"arr3: %s", object_getClassName(arr3)); // arr3: __NSArrayM
可以看出 [NSMutableArray array] 等同于[ [NSMutableArray alloc] init],都是可变数组类 __NSArrayM;
__NSPlaceholderArray:alloc时的对象先统一为这个类对象;
__NSArrayM:可变数组类;
3.2、分别对arr1、arr2、arr3进行copy和mutableCopy操作:
NSLog(@"arr1: %s", object_getClassName([arr1 copy])); // arr1: __NSArray0
NSLog(@"arr2: %s", object_getClassName([arr2 copy])); // arr2: __NSSingleObjectArrayI
NSLog(@"arr3: %s", object_getClassName([arr3 copy])); // arr3: __NSArrayI
NSLog(@"=================");
NSLog(@"arr1: %s", object_getClassName([arr1 mutableCopy])); // arr1: __NSArrayM
NSLog(@"arr2: %s", object_getClassName([arr2 mutableCopy])); // arr2: __NSArrayM
NSLog(@"arr3: %s", object_getClassName([arr3 mutableCopy])); // arr3: __NSArrayM
对不可变数组进行copy会改变为对应的不可变数组类名,但mutableCopy不会改变数组;
4、方法持有数组
NSLog(@"==%@",arr3);
NSLog(@"arr3: %p", arr3); // arr2: 0x608000014050
[self exchangeMArr:arr3];
NSLog(@"==%@",arr3);
NSLog(@"arr3: %p", arr3); // arr2: 0x608000014050
- (void)exchangeMArr:(NSMutableArray *)arr{
NSMutableArray *arr1 = arr;
[arr1 removeLastObject];
NSLog(@"arr3: %p", arr1); // arr2: 0x608000014050
}
结果:
-- ::05.902187+ ArrTest[:] ==(
, )
-- ::05.902476+ ArrTest[:] arr3: 0x60400024b100
-- ::05.902828+ ArrTest[:] arr3: 0x60400024b100
-- ::05.903073+ ArrTest[:] ==( )
-- ::05.903227+ ArrTest[:] arr3: 0x60400024b100
发现数组的地址不会发生改变,方法里对arr进行修改后,arr3也会发生改变;
所以如果处理数据时不希望arr3被影响,需要对其进行初始化或者copy就行;
5、__NSPlaceholderArray简单说明
对NSArray和NSMutableArray进行alloc时生成的都是__NSPlaceholderArray类,只有在init时才会返回是不可变或者可变数组。
这种情况如NSNumber、NSString都是这样,这就是类蔟(Class clusters)的设计模式。
iOS之NSArray类簇简介-(copy、mutableCopy导致程序crash)的更多相关文章
- iOS开发-retain/assign/strong/weak/copy/mutablecopy/autorelease区别
依旧本着尊重原创和劳动者的原则,将地址先贴在前面: http://www.cnblogs.com/nonato/archive/2013/11/28/3447162.html,作者Nonato 以下内 ...
- iOS开发-类簇(Class Cluster)
类簇(Class Cluster)是定义相同的接口并提供相同功能的一组类的集合,仅公开接口的抽象类也可以称之为类簇的公共类,每个具体类的接口有公共类的接口抽象化,并隐藏在簇的内部.这些类一般不能够直 ...
- iOS 关键词assign、strong、copy、weak、unsafe_unretained
关键词assign.strong.copy.weak.unsafe_unretained 影响: 是否开辟新的内存 是否有引用计数增加 strong 指向并拥有该对象.其修饰的对象引用计数会 +1,该 ...
- iOS - 类簇
类簇是在Objective-C中Foundation Framework中广泛使用的一种设计模式 1.发现类簇(Class Cluster)的踪迹 //*> 执行下面代码 id obj1 = [ ...
- iOS copy&mutableCopy理解
Copy&mutableCopy 通过copy方法可以创建可变或不可变对象的不可变副本,通过mutableCopy可以创建可变或不可变对象的可变副本. 拷贝分为浅拷贝和深拷贝: 浅拷贝:指 ...
- IOS 杂笔-1(为什么不继承类簇?)
答:首先,类簇是可以继承的,并不是不可以.例如,我们可以选择继承NSSting,但是此时你用你自己设定的类去调用NSSting的一些方法时,会存在无法实现的问题,这是为什么呢. 1.类簇里有很多私有的 ...
- iOS开发知识点:理解assign,copy,retain变strong
一..h和.m文件的变化说明 1.对于.h头文件,主要是将属性定义由retain变为strong @property (retain, nonatomic) 变为 @property (strong, ...
- OC 类簇与复合
OC 类簇与复合 类簇: 类簇是Foundation框架中广泛使用的设计模式.类簇将一些私有的.具体的子类组合在一个公共的.抽象的超类下面,以这种方法来组织类可以简化一个面向对象框架的公开架构,而又不 ...
- IOS atomic与nonatomic,assign,copy与retain的定义和区别
IOS atomic与nonatomic,assign,copy与retain的定义和区别 atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作. ...
随机推荐
- pycharm破解教程
转载 查询 https://blog.csdn.net/u014044812/article/details/86679150
- vue之自定义指令
1.自定义指令的作用 除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令.注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件.然而,有的情况下,你仍 ...
- Flink开发-IDEA scala开发环境搭建
现在大数据相关服务,越来越倾向于使用scala语言,scala函数式编程的优势我不多赘述.最明显的一个优点,代码简洁.看个WordCount实现对比: Java版WordCount Execution ...
- Java 二叉树遍历相关操作
BST二叉搜索树节点定义: /** * BST树的节点类型 * @param <T> */ class BSTNode<T extends Comparable<T>&g ...
- leetcood学习笔记-404-左叶子之和
题目描述: 方法一:递归 class Solution: def sumOfLeftLeaves(self, root: TreeNode) -> int: if not root: retur ...
- Android中的Serialable和Parcelable的区别
本文主要介绍Parcelable和Serializable的作用.效率.区别及选择,关于Serializable的介绍见<Java中的序列化Serialable高级详解> 1.作用 Ser ...
- 后缀自动机求LCS——spoj-LCS
经典题 注意匹配的时候:用t串去s串的SAM里进行匹配,和字典树一样遍历t中字符,用cur记录当前已经匹配的长度,如果能当前字符能匹配则cur++(这里不能直接用cur=len[now]),反之用li ...
- .net 项目如何添加log4net日志记录
1.在项目根目录新建文件log4net.config,此文件中的节点解释还请自动百度. 文件实例: <?xml version="1.0"?><configura ...
- jquery判断对象是undifined,判断对象是null
判断对象是undifined: var aaa = undefined; if (typeof(aaa) == "undefined") { ... } typeof 返回的是字符 ...
- Linux网络配置 RPM命令 samba服务 Linux目录结构
第一种方法: (1)用root身份登录,运行setup命令进入到 text mode setup utiliy对网络进行配置,这里可以进行ip,子网掩码,默认网关,dns的设置.(2)这时网卡的配置没 ...