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)的更多相关文章

  1. iOS开发-retain/assign/strong/weak/copy/mutablecopy/autorelease区别

    依旧本着尊重原创和劳动者的原则,将地址先贴在前面: http://www.cnblogs.com/nonato/archive/2013/11/28/3447162.html,作者Nonato 以下内 ...

  2. iOS开发-类簇(Class Cluster)

    类簇(Class  Cluster)是定义相同的接口并提供相同功能的一组类的集合,仅公开接口的抽象类也可以称之为类簇的公共类,每个具体类的接口有公共类的接口抽象化,并隐藏在簇的内部.这些类一般不能够直 ...

  3. iOS 关键词assign、strong、copy、weak、unsafe_unretained

    关键词assign.strong.copy.weak.unsafe_unretained 影响: 是否开辟新的内存 是否有引用计数增加 strong 指向并拥有该对象.其修饰的对象引用计数会 +1,该 ...

  4. iOS - 类簇

    类簇是在Objective-C中Foundation Framework中广泛使用的一种设计模式 1.发现类簇(Class Cluster)的踪迹 //*> 执行下面代码 id obj1 = [ ...

  5. iOS copy&mutableCopy理解

    Copy&mutableCopy   通过copy方法可以创建可变或不可变对象的不可变副本,通过mutableCopy可以创建可变或不可变对象的可变副本. 拷贝分为浅拷贝和深拷贝: 浅拷贝:指 ...

  6. IOS 杂笔-1(为什么不继承类簇?)

    答:首先,类簇是可以继承的,并不是不可以.例如,我们可以选择继承NSSting,但是此时你用你自己设定的类去调用NSSting的一些方法时,会存在无法实现的问题,这是为什么呢. 1.类簇里有很多私有的 ...

  7. iOS开发知识点:理解assign,copy,retain变strong

    一..h和.m文件的变化说明 1.对于.h头文件,主要是将属性定义由retain变为strong @property (retain, nonatomic) 变为 @property (strong, ...

  8. OC 类簇与复合

    OC 类簇与复合 类簇: 类簇是Foundation框架中广泛使用的设计模式.类簇将一些私有的.具体的子类组合在一个公共的.抽象的超类下面,以这种方法来组织类可以简化一个面向对象框架的公开架构,而又不 ...

  9. IOS atomic与nonatomic,assign,copy与retain的定义和区别

    IOS atomic与nonatomic,assign,copy与retain的定义和区别 atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作.        ...

随机推荐

  1. nginx 简单使用

    一,下载 http://nginx.org/en/download.html 这个是我下载的windows版本 二,解压后目录 三,修改配置文件 (由于80端口很可能被 SQL Server Repo ...

  2. vue 学习一 组件生命周期

    先上一张vue组件生命周期的流程图 以上就是一个组件完整的生命周期,而在组件处于每个阶段时又会提供一些周期钩子函数以便我们进行一些逻辑操作,而总体来讲 vue的组件共有8个生命周期钩子 beforeC ...

  3. docker一键部署zookeeper

    version: '3.1' services: zoo1: image: zookeeper:3.4.11 restart: always hostname: zoo1 container_name ...

  4. Linux下安装.NETCore3.0

    今天把.NETCore从2.2升到3.0记录一下 Download .NET Core 3.0  :https://dotnet.microsoft.com/download/dotnet-core/ ...

  5. js求100以内的素数

    //打印2~100之间的数 ; i< ; i++){ var a = true; ; j < i; j++){ //判断i能否被j整除 ){ //能被整除则说明不是素数,修改布尔值为fal ...

  6. vue+elementui 中 @keyup 键盘上下左右移动聚焦

    <template> <el-table :data="CreditUnclearOutlineList" border style="width: 1 ...

  7. c++ 在类函数后加const的意义

    我们定义的类的成员函数中,常常有一些成员函数不改变类的数据成员,也就是说,这些函数是"只读"函数,而有一些函数要修改类数据成员的值.如果把不改变数据成员的函数都加上const关键字 ...

  8. bzoj1012题解

    [解题思路] 强制在线线段树/树状数组,没什么好说的..复杂度O(mlog2m)(线段树)或O(mlog22m)(树状数组). [参考代码] (还naive的时候写的zkw真是翔..) #includ ...

  9. Delphi中任务栏状态区的编程

    在Windows桌面的任务栏上有一个凹陷的区域,其中显示着系统时钟以及一些图标,这个长方形的区域便是Windows的任务栏状态区(taskbar status area).本文将介绍使用Borland ...

  10. SP2713 GSS4 - Can you answer these queries IV(线段树)

    传送门 解题思路 大概就是一个数很少次数的开方会开到\(1\),而\(1\)开方还是\(1\),所以维护一个和,维护一个开方标记,维护一个区间是否全部为\(1/0\)的标记.然后每次修改时先看是否有全 ...