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
相关产品推荐
相关产品推荐

