美文网首页人猿星球iOS面试
iOS开发笔记——NSMutableArray与NSArray该

iOS开发笔记——NSMutableArray与NSArray该

作者: 勤奋的小卫子 | 来源:发表于2019-05-19 22:37 被阅读48次

    在项目开发中,时常听到大佬说创建NSArray属性要使用copy关键词,创建NSMutableArray属性要用strong关键词,一开始并不理解,直到程序crash的时候才追悔莫及😭

    目录

    • 一、操作NSmutableArray
      • 1.现象
      • 2.疑问
      • 3.小结
    • 二、操作NSArray
      • 1.现象
      • 2.小结
    • 三、总结

    一、操作NSMutableArray

    首先我们声明2NSMutableArray类型的属性:

    // 分别用copy与strong修饰他们
    @property (nonatomic, strong) NSMutableArray *array1;
    @property (nonatomic, copy)   NSMutableArray *array2;
    
    

    接着我们对他们分别赋值:

    // 声明数组
    NSMutableArray *array5 = [NSMutableArray arrayWithObjects:@"a",@"b",nil];
    self.array1 = array5; // NSMutableArray strong
    self.array2 = array5; // NSMutableArray copy
    // 打印数据与类型
    NSLog(@"array1:%@,类型:%@",self.array1,self.array1.class);
    NSLog(@"array2:%@,类型:%@",self.array2,self.array2.class);[self.array2 addObject:@"C"];
        
    

    打印结果:

    2019-05-19 22:05:12.969174+0800 tableView[16008:580852] array1:(
        a,
        b
    ),类型:__NSArrayM
    2019-05-19 22:05:12.969296+0800 tableView[16008:580852] array2:(
        a,
        b
    ),类型:__NSArrayI
    2019-05-19 22:05:12.969391+0800 tableView[16008:580852] -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x600002643b20
    

    1.现象:

    1.程序直接crash,并且可以看到array2的类型发生了变化(NSMutableArray变成NSArray)

    2.疑问:

    Q:为什么一个用strong修饰,另一个用copy修饰?
    A:因为其对应的setter方法实现不一样:

    // copy修饰
    - (void)setArray2:(NSMutableArray *)array2 {
        if (_array2 != array2) {
            [_array2 release];
            _array2 = [array2 copy]; // 内容拷贝,深拷贝
        }
    }
    
    // strong修饰
    - (void)setArray1:(NSMutableArray *)array1 {
        if (_array1 != array1) {
            [_array1 release];
            _array1 = [array1 retain]; // 指针拷贝,浅拷贝
        }
    }
    

    不管集合类对象(NSArray,NSDictionary)还是非集合对象(NSString),接收到copy或者mutableCopy消息时,都遵循以下准则:

    • copy 创建可变对象或者不可变对象的不可变副本,对于不可变副本,对象的值不能改变,如果对copy返回值执行增删改操作就会crash
    • mutableCopy 创建出的是可变对象或不可变对象的可变副本

    3.小结:

    修饰NSMutableArray属性时,请使用strong,使用copy会造成crash!!!

    二、操作NSArray

    // 声明两个属性,分别用strong和copy修饰
    @property (nonatomic, strong) NSArray *array1;
    @property (nonatomic, copy)   NSArray *array2;
    
    // 声明数组
    NSMutableArray *array5 = [NSMutableArray arrayWithObjects:@"a",@"b",nil];
    self.array1 = array5; // NSArray strong
    self.array2 = array5; // NSArray copy
    [array5 addObject:@"c"];
    
    NSLog(@"array1:%@,类型:%@",self.array1,self.array1.class);
    NSLog(@"array2:%@,类型:%@",self.array2,self.array2.class);
    

    打印:

    2019-05-19 22:23:50.245323+0800 tableView[16333:600961] array1:(
        a,
        b,
        c
    ),类型:__NSArrayM
    2019-05-19 22:23:50.245445+0800 tableView[16333:600961] array2:(
        a,
        b
    ),类型:__NSArrayI
    

    1.现象

    • 如果使用strong声明一个NSArray属性,那么这个属性有可能指向一个可变对象,并且可能在该属性不知情的情况下造人修改
    • 因此最好拷贝一份不可变的数据,确保不会意外的被修改。

    2.小结

    NSArray类型使用copy修饰,防止值和类型被意外修改;
    使用strong修饰时,值和类型可能会被修改

    三、总结

    • 声明类型为NSArray的属性时,使用copy修饰
      • 防止类型被修改
      • 防止值被修改
    • 声明类型为NSMutableArray的属性时,使用strong修饰
      • 防止类型被修改,从而造成crash

    相关文章

      网友评论

        本文标题:iOS开发笔记——NSMutableArray与NSArray该

        本文链接:https://www.haomeiwen.com/subject/gqeczqtx.html