• 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:@0, nil];
        NSArray *arr3 = [placeholder initWithObjects:@0, @1, 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:@0, nil];
        NSMutableArray *arr3 = [arr initWithObjects:@0, @1, nil];
        NSMutableArray *arr4 = [arr initWithObjects:@0, @1, @2, 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
    }

      结果:

    2018-06-11 14:52:05.902187+0800 ArrTest[5672:265513] ==(
        0,
        1
    )
    2018-06-11 14:52:05.902476+0800 ArrTest[5672:265513] arr3: 0x60400024b100
    2018-06-11 14:52:05.902828+0800 ArrTest[5672:265513] arr3: 0x60400024b100
    2018-06-11 14:52:05.903073+0800 ArrTest[5672:265513] ==(
        0
    )
    2018-06-11 14:52:05.903227+0800 ArrTest[5672:265513] arr3: 0x60400024b100

      发现数组的地址不会发生改变,方法里对arr进行修改后,arr3也会发生改变;

      所以如果处理数据时不希望arr3被影响,需要对其进行初始化或者copy就行;

    5、__NSPlaceholderArray简单说明

      对NSArray和NSMutableArray进行alloc时生成的都是__NSPlaceholderArray类,只有在init时才会返回是不可变或者可变数组。

      这种情况如NSNumber、NSString都是这样,这就是类蔟(Class clusters)的设计模式。

  • 相关阅读:
    结对项目:四则运算
    Word Count(C语言)
    自我介绍+软工5问
    如何在博客园中使用markdown
    如何设计一门语言(九)——类型
    如何设计一门语言(八)——异步编程和CPS变换
    如何设计一门语言(七)——闭包、lambda和interface
    时隔多年我又再一次体验了一把跟大神聊天的感觉
    20199107 2019-2020-2 《网络攻防实践》第4周作业
    20199107 2019-2020-2 《网络攻防实践》第3周作业
  • 原文地址:https://www.cnblogs.com/xianfeng-zhang/p/9167108.html
Copyright © 2020-2023  润新知