陈斌彬的技术博客

Stay foolish,stay hungry

OC中copy和mutableCopy详解

在OC中,最为重要的一点就是内存管理。而在内存管理时,有时会遇到copy出来的对象,是否需要释放内存的情况。所以,本文将讲解下copy与mutableCopy的用法和区别。

正文:

1. 首先需要关闭ARC模式。

2. 以下所有内容都将以NSString作为例子进行讲解。

3. copy复制出来的对象都是不可变对象。

//对于不可变字符串,copy类似与retain(浅copy)
NSString *string1 = [[NSString alloc] initWithFormat:@"字符串1"];
NSString *newString1 = [string1 copy];
NSLog(@"%ld", [string1 retainCount]); //2

不可变字符串(字典、集等),copy操作相当于retain(指针拷贝)。

这种copy方式,不会分配内存,只是让newString1持有了string1的内存。

img

//对于可变字符串,copy会重新开辟空间(深copy)
NSMutableString *string2 = [[NSMutableString alloc] initWithFormat:@"字符串2"];
NSMutableString *newString2 = [string2 copy];
NSLog(@"%ld", [string2 retainCount]); //1

可变字符串(字典、集等),copy操作相当于alloc并且赋值(内存拷贝)。这种copy方式,会重新分配内存。

所以对newString2操作(修改、release等)并不会影响到string2,因为他们没有在操作同一块内存。

img

因为copy出来的都是不可变对象,所以这里的newString2,即使是NSMutableString类型,但不能调用可变对象的方法,因为newString2已经是不可变对象了。 如果强制调用,程序崩溃,并报错:‘Attempt to mutate immutable object with deleteCharactersInRange:…’试图修改一个不可变的对象

4. mutableCopy复制出来的对象都是可变对象,并且对于NSString和NSMutableString都是内存拷贝(深copy)。

//对于不可变和可变对象,都是内容复制(深copy)
NSString *string3 = [[NSString alloc] initWithFormat:@"字符串3"];
NSString *newString3 = [string3 mutableCopy];
NSLog(@"%ld", [string3 retainCount]); //1

虽然使用了NSString去接收了mutableCopy出来的string3,但是newString3依然是一个可变字符串,可以调用可变字符串的方法,但是会报警告,因为子类调用了父类的方法。

img

NSMutableString *string4 = [[NSMutableString alloc] initWithFormat:@"字符串4"];
NSMutableString *newString4 = [string4 mutableCopy];
NSLog(@"%ld", [string4 retainCount]); //1

对于可变字符串,mutableCopy依然是可变。

img

总结:

img