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

Swift中修改ScoreModel数组内HoleScore属性时的批量变更异常

解决Swift中修改数组内模型属性导致所有实例同步变化的问题

嘿,这个问题我之前踩过坑!核心原因是Swift里的类是引用类型——你肯定是在创建ScoreModel实例的时候,不小心让多个实例共享了同一个HoleScore对象(或者同一个holeScores数组里的元素),导致改一个属性,所有指向这个对象的引用都会跟着变。

比如举个反例,如果你是这么创建数组的:

// 错误示范:复用同一个HoleScore实例
let sharedHoleScore = HoleScore()
let holeScores = [sharedHoleScore]

let model1 = ScoreModel()
model1.holeScores = holeScores
let model2 = ScoreModel()
model2.holeScores = holeScores

scoreList = [model1, model2]

这时候model1和model2的holeScores[0]指向的是同一个sharedHoleScore对象,你改其中一个的holeScore,另一个自然也会同步变化,因为它们本质上操作的是内存里的同一个对象。

解决方案:确保每个实例都是独立的

要解决这个问题,关键是让每个ScoreModel的holeScores数组及其内部的HoleScore实例都是全新创建的,不要复用同一个对象引用。

1. 手动创建独立实例

创建每个ScoreModel的时候,单独初始化它的holeScores数组和里面的HoleScore对象:

// 创建第一个独立的ScoreModel
let model1 = ScoreModel()
model1.playerId = 1
model1.holeScores = [HoleScore()] // 这里每次都生成新的HoleScore实例

// 创建第二个独立的ScoreModel
let model2 = ScoreModel()
model2.playerId = 2
model2.holeScores = [HoleScore()]

scoreList = [model1, model2]

现在再执行scoreList[0].holeScores![0].holeScore = 3,就只有model1的属性会被修改,model2的保持原样。

2. 用工厂方法批量创建(更高效)

如果需要创建多个实例,写个工厂方法来统一生成独立的模型,避免重复代码:

extension ScoreModel {
    static func makePlayerScore(playerId: Int, holeCount: Int = 18) -> ScoreModel {
        let model = ScoreModel()
        model.playerId = playerId
        // 为每个洞生成全新的HoleScore实例
        model.holeScores = (1...holeCount).map { _ in HoleScore() }
        return model
    }
}

// 批量生成独立的ScoreModel实例
scoreList = [
    ScoreModel.makePlayerScore(playerId: 1),
    ScoreModel.makePlayerScore(playerId: 2),
    ScoreModel.makePlayerScore(playerId: 3)
]

3. 优化模型(可选但推荐)

建议尽量避免使用可选类型,减少强制解包!带来的崩溃风险,同时让模型更健壮:

class ScoreModel {
    var playerId: Int
    var holeScores: [HoleScore]
    
    // 初始化方法强制传入必要参数
    init(playerId: Int, holeScores: [HoleScore]) {
        self.playerId = playerId
        self.holeScores = holeScores
    }
}

class HoleScore {
    var holeScore: Int = 0 // 给默认值,避免可选
    
    init(holeScore: Int = 0) {
        self.holeScore = holeScore
    }
}

这样创建实例的时候更清晰,也不会出现nil的情况:

let model1 = ScoreModel(playerId: 1, holeScores: [HoleScore()])
scoreList.append(model1)

总结

本质就是要区分值类型和引用类型的差异:Swift的类是引用类型,赋值的时候传递的是内存地址,而不是对象本身。只要保证每个ScoreModel及其内部的HoleScore都是独立创建的实例,就不会出现“牵一发而动全身”的问题了。

内容的提问来源于stack exchange,提问作者Mujahid Latif

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:23:59