美文网首页
iOS 开发刷题系列二:copy和mutableCopy

iOS 开发刷题系列二:copy和mutableCopy

作者: 34码的小孩子 | 来源:发表于2017-12-05 21:26 被阅读10次

    @property 声明的NSString为何要使用copy来修饰?如果用strong,会发生什么?

    • 因为父类指针可以指向子类对象,使用拷贝的目的是为了让本对象的属性不受外界影响,使用拷贝无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本。

    • 如果我们使用是strong,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性。

        - (void)someFunctionWithArray:(NSArray *)array {
            self.array = array;
        }
      
        - (void)viewDidLoad {
            [super viewDidLoad];
      
            NSMutableArray *mutableArray = [NSMutableArray new];
            [mutableArray addObject:@"20"];
            [self someFunctionWithArray:mutableArray];
            NSLog(@"count = %@", self.array);
            [mutableArray addObject:@"40"];
            NSLog(@"count = %@", self.array);
        }
      

    打印结果如下:

        2017-12-05 20:09:02.862459+0800 TestDemo[4435:1823871] count = (
    20
    )
        2017-12-05 20:09:02.862656+0800 TestDemo[4435:1823871] count = (
    20,
    40
    )
    

    如果将strong改为copy, 打印结果如下:

    2017-12-05 20:13:37.365180+0800 TestDemo[4471:1860623] count = (
    20
    )
    2017-12-05 20:13:37.365383+0800 TestDemo[4471:1860623] count = (
    20
    )
    

    引申另外一个问题:如果声明NSMutableArray等可变对象使用copy修饰,会有什么问题?

    NSArray *array = @[@"1", @"2", @"3", @"4"];
    NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithArray:array];
    self.mutableArray = mutableArray;
    [self.mutableArray addObject:@"20"];
    

    会出现以下Crash:

    2017-12-05 21:08:24.756887+0800 TestDemo[4844:2215665] -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x600000246090
    

    使用copy修饰可变对象,在进行赋值的时候,是使用copy方法的。而此时self.mutableArray得到的实际上是一个不可变数组。当你对数组进行增删操作时,会crash。

    非集合类对象的copy和mutableCopy

    NSMutableString *string = [NSMutableString stringWithString:@"MutableString"];
     // 可变对象的copy, 指向不同地址
    NSString *stringCopy = [string copy];
    // 不可变字符串copy,指向的是同一个地址
    NSString *stringCopy2 = [stringCopy copy];
    // 不可变字符串的mutableCopy,指向的是不同的地址
    NSMutableString *mutableCopy = [stringCopy mutableCopy];
    // 可变字符串的mutableCopy,指向的是不同的地址
    NSMutableString *mutableCopy2 = [string mutableCopy];
    
    NSLog(@"MutableString = %p", string);
    NSLog(@"stringCopy = %p", stringCopy);
    NSLog(@"stringCopy2 = %p", stringCopy2);
    NSLog(@"mutableCopy = %p", mutableCopy);
    NSLog(@"mutableCopy2 = %p", mutableCopy2);
    

    打印输出如下:

    2017-12-05 20:27:17.194786+0800 TestDemo[4647:1943709] MutableString = 0x60400025a5b0
    2017-12-05 20:27:17.194951+0800 TestDemo[4647:1943709] stringCopy = 0x6040000367e0
    2017-12-05 20:27:17.195040+0800 TestDemo[4647:1943709] stringCopy2 = 0x6040000367e0
    2017-12-05 20:27:17.195138+0800 TestDemo[4647:1943709] mutableCopy = 0x60400025a9d0
    2017-12-05 20:27:17.195642+0800 TestDemo[4647:1943709] mutableCopy2 = 0x60400025a610
    

    结果如下:
    指向不同地址, 是内容复制,也就是深拷贝 :

    • [mutableObject copy]
    • [mutableObject mutableCopy]
    • [immutableObject mutableCopy]

    指向同一个地址,是指针复制,也就是浅拷贝:

    • [immutableObject copy]

    集合类对象的copy和mutableCopy

    不可变集合的copy和mutableCopy

    NSArray *array = @[@"1", @"2", @"3", @"4"];
    // 不可变集合copy进行了指针拷贝,两者地址一致
    NSArray *copyArray = [array copy];
    // 不可变集合mutableCopy进行了内容复制,两者地址不一致
    NSMutableArray *mutableArray = [array mutableCopy];
    
    NSLog(@"array = %p", array);
    NSLog(@"copyArray = %p", copyArray);
    NSLog(@"mutableArray = %p", mutableArray);
    

    打印结果如下:

    2017-12-05 20:47:31.521896+0800 TestDemo[4719:2064317] array = 0x604000259a10
    2017-12-05 20:47:31.522040+0800 TestDemo[4719:2064317] copyArray = 0x604000259a10
    2017-12-05 20:47:31.522125+0800 TestDemo[4719:2064317] mutableArray = 0x604000259e30
    

    可变集合的copy和mutableCopy

    NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithArray:array];
    // 可变集合的copy进行了内容复制,两者地址不一致
    NSArray *copyArray = [mutableArray copy];
    // 可变集合的mutableCopy进行了内容复制,两者地址不一致。
    NSMutableArray *mutableCopyArray = [mutableArray mutableCopy];
    
    NSLog(@"mutableArray = %p", mutableArray);
    NSLog(@"copyArray = %p", copyArray);
    NSLog(@"mutableCopyArray = %p", mutableCopyArray);
    

    打印输出如下:

    2017-12-05 20:53:23.174059+0800 TestDemo[4762:2113125] mutableArray = 0x600000259fb0
    2017-12-05 20:53:23.174210+0800 TestDemo[4762:2113125] copyArray = 0x600000259e90
    2017-12-05 20:53:23.174303+0800 TestDemo[4762:2113125] mutableCopyArray = 0x600000259e00
    

    结果如下:
    指向不同地址,是单层深拷贝:

    • [immutableObject mutableCopy ]
    • [mutableObject copy ]
    • [mutableObject mutableCopy ]

    指向同一个地址,是浅拷贝:

    • [immutableObject copy ]

    集合的真正深复制:

    • 可以用 initWithArray:copyItems: 将第二个参数设置为YES即可深复制

    • 将集合进行归档(archive),然后解档(unarchive)。

        NSArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:oldArray]];
      

    相关文章

      网友评论

          本文标题:iOS 开发刷题系列二:copy和mutableCopy

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