You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何防止对象被覆盖?跨视图控制器赋值异常问题

问题原因与解决方案

这是典型的引用类型传递导致的问题,我来给你拆解清楚:

为什么会同步变更?

在iOS中,class类型是引用类型——当你把ViewController1.ObjectA赋值给ViewController2.ObjectB时,并没有创建一个新的对象,只是让ObjectB和ObjectA指向了内存中同一个对象实例。所以无论你修改哪个变量的属性,本质上都是在修改同一块内存里的数据,自然会同步变化。

而如果是struct或者enum这类值类型,赋值时会自动创建完整的副本,两个变量完全独立,修改其中一个不会影响另一个。

解决方法

根据你的需求,有几种可行的方案:

1. 实现深拷贝(推荐自定义类使用)

给你的自定义类实现NSCopying协议,创建一个独立的对象副本:

// 假设你的自定义类是这样的
class MyObject: NSObject, NSCopying {
    var title: String
    var count: Int
    
    init(title: String, count: Int) {
        self.title = title
        self.count = count
    }
    
    // 实现NSCopying协议的方法
    func copy(with zone: NSZone? = nil) -> Any {
        // 创建新对象并复制所有属性
        let copiedObject = MyObject(title: self.title, count: self.count)
        // 如果对象里还有其他引用类型的属性,需要递归调用copy()来完成深拷贝
        return copiedObject
    }
}

然后赋值的时候改用拷贝后的对象:

// 替换原有的直接赋值
viewController2.objectB = self.objectA.copy() as! MyObject

2. 将类改为结构体(适合简单数据模型)

如果你的对象不需要继承NSObject或者没有类特有的需求,直接把class改成struct即可:

struct MyObject {
    var title: String
    var count: Int
}

此时直接赋值viewController2.objectB = self.objectA,两个变量会是完全独立的副本,修改objectB不会影响objectA。

3. 手动创建副本(快速临时方案)

如果只是临时需求,不想修改类结构或实现协议,可以手动创建新对象并复制属性:

let newObject = MyObject(title: self.objectA.title, count: self.objectA.count)
viewController2.objectB = newObject

注意事项

如果你的对象包含其他引用类型的子属性(比如另一个自定义类的实例),在实现深拷贝时要记得递归拷贝这些子属性,否则这些子属性仍然会是引用传递,导致部分数据同步变更。

内容的提问来源于stack exchange,提问作者Zahurafzal Mirza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:40:14