Objective-C 类的 Copy 操作:深拷贝与浅拷贝对对象属性的影响

在 Objective-C 中,拷贝操作通过 NSCopyingNSMutableCopying 协议实现,其核心区别在于对象属性的复制深度

1. 浅拷贝 (Shallow Copy)
  • 定义:仅复制对象本身,不复制其内部属性对象
  • 属性影响
    • 新对象与原对象共享所有属性对象的引用
    • 修改新对象的属性会影响原对象
    • 适用于不可变属性(如 NSString
  • 实现示例
- (id)copyWithZone:(NSZone *)zone {
    MyClass *copy = [[[self class] alloc] init];
    copy.propertyA = self.propertyA; // 直接指针赋值
    copy.propertyB = self.propertyB; // 共享引用
    return copy;
}

2. 深拷贝 (Deep Copy)
  • 定义:递归复制对象及其所有属性对象
  • 属性影响
    • 新对象拥有完全独立的属性副本
    • 修改新对象属性不影响原对象
    • 必需用于可变属性(如 NSMutableArray
  • 实现示例
- (id)copyWithZone:(NSZone *)zone {
    MyClass *copy = [[[self class] alloc] init];
    copy.propertyA = [self.propertyA copy]; // 浅拷贝不可变对象
    copy.propertyB = [[NSMutableArray alloc] initWithArray:self.propertyB copyItems:YES]; // 深拷贝
    return copy;
}

3. 关键影响因素分析
属性类型 浅拷贝效果 深拷贝效果
NSString ✅ 安全(不可变) ⚠️ 冗余复制
NSMutableString ❌ 危险(共享可变状态) ✅ 必需
NSArray ✅ 安全(元素未复制) ⚠️ 元素仍共享
NSMutableArray ❌ 元素共享 ✅ 元素独立
自定义对象 ❌ 共享引用 ✅ 递归复制
4. 实现规范建议
  1. 不可变对象

    @property (copy) NSString *title; // 自动浅拷贝
    

    • 系统自动调用 [value copy]
    • NSString 实际是引用计数增加
  2. 可变对象

    NSMutableArray *deepCopy = [[NSMutableArray alloc] 
                                initWithArray:originalArray 
                                copyItems:YES];
    

    • 需递归实现 NSCopying
    • 使用 copyItems:YES 触发元素拷贝
  3. 自定义对象

    - (id)copyWithZone:(NSZone *)zone {
        MyClass *copy = [[[self class] alloc] init];
        copy.subObject = [self.subObject copy]; // 委托拷贝
        return copy;
    }
    

5. 内存模型对比
浅拷贝:
[对象A] --→ [属性X]
[对象B] --↗

深拷贝:
[对象A] --→ [属性X]
[对象B] --→ [属性X_copy]

最佳实践
  1. 声明 @property 时:

    • 不可变对象用 copy
    • 可变对象用 strong + 手动深拷贝
  2. 实现 copyWithZone: 时:

    • 基础类型直接赋值
    • 对象属性调用 copymutableCopy
    • 集合类型使用 initWithArray:copyItems:YES
  3. 避免:

    copy.property = [mutableObj retain]; // ❌ 错误:仍是浅拷贝
    

通过合理选择拷贝策略,可有效避免由对象共享导致的不可预测行为,确保数据状态的隔离性和线程安全。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐