iOS 中 copy 和 mutableCopy 详解

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

环境信息:
Mac OS X 10.9
Xcode 5.1.1

正文:

关闭 ARC 模式
以下所有内容都将以 NSString 作为例子进行讲解

copy 出来的对象都是不可变对象

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

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

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

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

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

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

NSMutableString的copy操作
NSMutableString 的 copy 操作

因为 copy 出来的都是不可变对象,所以这里的 newString2,即使是 NSMutableString 类型,但不能调用可变对象的方法,因为 newString2 已经是不可变对象了。

如果强制调用,程序崩溃,并报错:‘Attempt to mutate immutable object with deleteCharactersInRange:…’ 试图修改一个不可变的对象

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

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

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

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

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

NSMutableString的mutableCopy操作
NSMutableString 的 mutableCopy 操作

总结:

copy和mutableCopy总结
copy 和 mutableCopy 总结

《iOS 中 copy 和 mutableCopy 详解》有3个想法

  1. NSString mutableCopy那里“但是会报警告,因为子类调用了父类的方法”写错了吧,应该是父类调用了子类的方法。^_^

发表评论

电子邮件地址不会被公开。