TabBarView + 类模型数组异常:追加时现有元素被修改
解决TabBar控制器数组追加时现有元素被修改的问题
看起来你碰到的是Swift里引用类型和值类型行为差异的典型问题,咱们来理清楚根源和解决办法:
问题根源
你的customerInformation、Item、TotalInformation应该是用class定义的(引用类型),而String是值类型:
- 当你把
customerData这类数组追加到tabBar的数组中时,实际上存储的是对象的内存引用地址,而不是对象本身。后续如果修改原数组里的对象内容,tabBar数组里的对应元素会跟着变化——因为它们指向的是同一个内存里的对象。 - 而String数组正常,是因为值类型在赋值、追加操作时会自动创建完整的副本,原数据和新数据完全独立,互不影响。
解决方案
方案1:将自定义类型改为值类型(推荐)
把定义数据模型的class换成struct,Swift的结构体是值类型,默认会在赋值、追加时做值拷贝:
// 用struct替代class struct customerInformation { // 你的属性,比如: var id: String var name: String } struct Item { var itemId: Int var price: Double } struct TotalInformation { var totalAmount: Double var date: Date }
这样修改后,你原有的追加代码不需要改动,就能保证tabBar数组里的元素和原数组完全独立,修改其中一方不会影响另一方。
方案2:手动实现深拷贝(若必须使用class)
如果因为业务需求必须用类,那需要手动为每个类实现拷贝逻辑,确保追加的是对象的副本而非引用。比如用NSCopying协议:
- 让你的类实现
NSCopying:
class customerInformation: NSObject, NSCopying { var id: String = "" var name: String = "" // 实现拷贝方法,手动复制所有属性 func copy(with zone: NSZone? = nil) -> Any { let copied = customerInformation() copied.id = self.id copied.name = self.name // 复制其他自定义属性 return copied } }
- 追加时生成副本数组:
let tabBar = tabBarController as! baseTabBarController // 对数组里的每个对象做拷贝,生成新的独立数组 let copiedCustomerData = customerData.map { $0.copy() as! customerInformation } tabBar.customerData.append(copiedCustomerData) // itemsData和totalData做同样的处理 let copiedItemsData = itemsData.map { $0.copy() as! Item } tabBar.itemsData.append(copiedItemsData) let copiedTotalData = totalData.copy() as! TotalInformation tabBar.totalData.append(copiedTotalData)
验证小技巧
你可以在追加前后打印对象的内存地址,确认是否为同一个引用:
// 打印原数组第一个元素的地址 print("原对象地址:", Unmanaged.passUnretained(customerData[0]).toOpaque()) // 追加后打印tabBar数组里对应元素的地址 print("TabBar里的对象地址:", Unmanaged.passUnretained(tabBar.customerData.last![0]).toOpaque())
如果地址相同,就坐实了引用类型的问题;修改后地址不同,说明拷贝生效了。
内容的提问来源于stack exchange,提问作者todoMan
相关产品推荐
相关产品推荐

