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)的设计模式。

posted @ 2018-06-11 15:03  ForeverGuard  阅读(772)  评论(0编辑  收藏  举报