
你瞅啥!瞅你咋地
在 iOS 中,最為重要的一點就是內(nèi)存管理。而在內(nèi)存管理時,有時會遇到 copy 出來的對象,是否需要釋放內(nèi)存的情況。所以,本文將講解下
copy與mutableCopy的用法和區(qū)別。
注:關(guān)閉 ARC 模式
以下所有內(nèi)容都將以 NSString 作為例子進行講解
-
重要規(guī)則:
- 目的:類似文件夾,拷貝備份之后,源文件修改不影響copy文件,同時,copy文件修改也不影響源文件。總結(jié):拷貝之后,互不影響
- 不可變對象:copy直接引用計數(shù)+1,互相修改也不會影響;mutableCopy的副本能修改,則需生成新的對象;
- 可變對象:copy和mutableCopy的源本能修改,則需生成新的對象。
- 目的:類似文件夾,拷貝備份之后,源文件修改不影響copy文件,同時,copy文件修改也不影響源文件。總結(jié):拷貝之后,互不影響
copy
重點:copy 出來的對象都是不可變對象
// 對于不可變字符串,copy 類似與 retain(淺copy)
NSString *string1 = [[NSString alloc] initWithFormat:@"字符串1"];
NSString *newString1 = [string1 copy];
NSLog(@"%ld", [string1 retainCount]); //2
不可變字符串(字典、集等),copy 操作相當(dāng)于 retain(指針拷貝)。
這種 copy 方式,不會分配內(nèi)存,只是讓 newString1 持有了 string1 的內(nèi)存。

不可變對象的copy操作
// 對于可變字符串,copy 會重新開辟空間(深 copy)
NSMutableString *string2 = [[NSMutableString alloc] initWithFormat:@"字符串2"];
NSMutableString *newString2 = [string2 copy];
NSLog(@"%ld", [string2 retainCount]); //1
可變字符串(字典、集等),copy 操作相當(dāng)于 alloc 并且賦值(內(nèi)存拷貝)。這種 copy 方式,會重新分配內(nèi)存。
所以對 newString2 操作(修改、release 等)并不會影響到 string2,因為他們沒有在操作同一塊內(nèi)存。

可變對象的copy操作
因為
copy 出來的都是不可變對象,所以這里的 newString2,即使是 NSMutableString 類型,但不能調(diào)用可變對象的方法,因為 newString2 已經(jīng)是不可變對象了。
如果強制調(diào)用,程序崩潰,并報錯:‘Attempt to mutate immutable object with deleteCharactersInRange:…’ 試圖修改一個不可變的對象
mutableCopy
重點:mutableCopy 復(fù)制出來的對象都是可變對象,并且對于 NSString 和 NSMutableString 都是內(nèi)存拷貝(深copy)
// 對于不可變和可變對象,都是內(nèi)容復(fù)制(深 copy)
NSString *string3 = [[NSString alloc] initWithFormat:@"字符串3"];
NSString *newString3 = [string3 mutableCopy];
NSLog(@"%ld", [string3 retainCount]); //1
雖然使用了 NSString 去接收了 mutableCopy 出來的 string3,但是 newString3 依然是一個可變字符串,可以調(diào)用可變字符串的方法,但是會報警告,因為子類調(diào)用了父類的方法。

不可變對象的mutableCopy操作
NSMutableString *string4 = [[NSMutableString alloc] initWithFormat:@"字符串4"];
NSMutableString *newString4 = [string4 mutableCopy];
NSLog(@"%ld", [string4 retainCount]); // 1
對于可變字符串,mutableCopy 依然是可變。

可變對象的mutableCopy操作
總結(jié)
| 對象類型 | copy | mutableCopy |
|---|---|---|
| 不可變對象 | 淺copy,指針復(fù)制,返回值不可變 | 深copy,內(nèi)容復(fù)制,返回值可變 |
| 可變對象 | 深copy,內(nèi)容復(fù)制,返回值不可變 | 深copy,內(nèi)容復(fù)制,返回值可變 |