| 方法 | 返回物件 | 可變性 | 記憶體管理 |
copy | 新物件 | 不可變 | 調用者負責 release (MRC) / 持有 (ARC) |
mutableCopy | 新物件 | 可變 | 同 copy |
原物件 retainCount 不變,無需釋放原物件。
自定義類別實現 NSCopying (淺拷貝)
@interface BankAccount : NSObject {
double accountBalance;
long accountNumber;
}
- (void)setAccount:(long)number andBalance:(double)balance;
- (id)copyWithZone:(NSZone *)zone;
@end
@implementation BankAccount
- (id)copyWithZone:(NSZone *)zone {
BankAccount *copy = [[[self class] allocWithZone:zone] init];
[copy setAccount:accountNumber andBalance:accountBalance];
return copy;
}
@end
淺拷貝特徵:僅複製指標值,指向同一記憶體區塊。修改其中一個物件的屬性(如 NSMutableString*),另一個也會受影響。
深拷貝:利用歸檔/解檔實現真正獨立
NSArray *myArray1 = @[@"Red", @"Green", @"Blue"]; // 含可變物件
// 歸檔 -> 序列化為 NSData
NSData *buffer = [NSKeyedArchiver archivedDataWithRootObject:myArray1];
// 解檔 -> 反序列化為新物件圖
NSArray *myArray2 = [NSKeyedUnarchiver unarchiveObjectWithData:buffer];
// 驗證獨立性
NSMutableString *str1 = myArray1[0];
[str1 setString:@"Yellow"]; // 修改原陣列元素
NSLog(@"myArray1[0]: %@", myArray1[0]); // Yellow
NSLog(@"myArray2[0]: %@", myArray2[0]); // Red (未受影響)
原理:NSKeyedArchiver 遞歸編碼整個物件圖,NSKeyedUnarchiver 重建全新物件樹,實現完全深拷貝。要求所有涉及類別實現 NSCoding 協議 (encodeWithCoder:, initWithCoder:)。
屬性修飾符與 copy 的協作
@property (copy) NSString *name; // setter 內部調用 [newValue copy]
@property (copy) NSArray *items; // 確保內部持有不可變快照
@property (strong) NSMutableArray *mutableItems; // 內部需可變時用 strong
copy 修飾符適用於有可變對應類別的不可變類別 (NSString/NSArray/NSDictionary/NSIndexSet...)
- 自定義類別若想支援
@property(copy),必須實現 copyWithZone:
實戰陷阱與最佳實踐
- 集合類別的 copy 是單層淺拷貝:
[array copy] 新陣列元素仍指向舊物件。需深拷貝請用歸檔或手動遞歸複製。
- 不可變類別的 copy 優化:
[NSString copy] 通常返回 self (retain),不分配新記憶體,效能極高。
- MRC 環境記憶體管理:
NSString *copy = [original copy]; // retainCount +1
[copy release]; // 用完必須釋放
- ARC 環境:編譯器自動插入
retain/release,但語義不變。
總結決策樹
需要複製物件?
├─ 是不可變類別 (NSString, NSArray...) → 直接 copy (極快,可能是 retain)
├─ 需要可變副本 → mutableCopy
├─ 自定義類別 → 實現 NSCopying (淺拷貝) 或 NSCoding + 歸檔 (深拷貝)
└─ 集合類別深拷貝 → NSKeyedArchiver/Unarchiver (需所有元素支援 NSCoding)
- 上一篇文章: Objective-C 時間戳與 NSDate 互轉完整指南
- 下一篇文章: C語言編程經驗積累(四):從 sizeof 陷阱到結構體對齊的 30 個實戰筆記
Copyright ©
程式碼之家 All Rights Reserved