Swift数组存储元素:选Class还是Struct?修改属性存困惑
要不要把Game/Player换成Class?先捋清这几点
嘿,我太懂你这种纠结了——Swift天天喊着优先用值类型,结果碰到数组里改Struct属性的场景,总觉得不如引用类型顺手。咱们一步步拆解,看看哪种选择更适合你的场景:
1. 先别急着换Class,值类型也有优雅的修改方式
你觉得“重新赋值”不妥,大概率是没用到Swift为值类型设计的便捷写法。针对数组里的Struct,这两种方法能帮你摆脱繁琐的重新赋值:
方法一:利用下标+mutating方法直接修改
给你的Player Struct加个mutating方法封装属性修改,然后通过数组下标直接调用,Swift会自动处理值的复制和替换:
struct Player { var name: String var score: Int // 用mutating方法封装修改逻辑 mutating func addScore(_ points: Int) { score += points } } struct Game { var players: [Player] } // 使用示例 var myGame = Game(players: [ Player(name: "Alice", score: 0), Player(name: "Bob", score: 0) ]) // 找到要修改的玩家下标,直接调用mutating方法 if let aliceIndex = myGame.players.firstIndex(where: { $0.name == "Alice" }) { myGame.players[aliceIndex].addScore(100) }
这种写法和修改Class属性一样简洁,还保留了值类型的安全性。
方法二:用inout封装批量修改逻辑
如果修改逻辑比较复杂,或者需要多次修改,把逻辑封装成带inout参数的函数,调用时直接传数组的引用:
func updatePlayerScore(in players: inout [Player], named playerName: String, newScore: Int) { guard let index = players.firstIndex(where: { $0.name == playerName }) else { return } players[index].score = newScore } // 调用时只需传&数组 updatePlayerScore(in: &myGame.players, named: "Bob", newScore: 150)
这样调用方的代码会非常清爽,不用每次都写找下标、修改、替换的重复逻辑。
2. 什么时候真的需要换成Class?
如果你的场景满足以下任意一种,Class会是更合适的选择:
- 需要多模块共享状态:比如你的
Game或Player实例在多个ViewModel、ViewController里被引用,修改一个地方的属性后,其他地方需要实时看到变化——这时候引用类型的共享特性会省掉大量同步值的麻烦。 - 需要继承扩展:如果之后要给
Player做子类(比如VIPPlayer、GuestPlayer),Class支持继承,而Struct只能靠协议实现类似的多态,成本更高。 - 需要身份标识:如果两个
Player即使属性完全一样,你也需要区分它们是“不同的实例”(比如两个同名同分数的玩家,但实际是不同的用户),Class的引用身份会比Struct的值相等更有用。
3. 给你的具体建议
- 如果是简单单机小游戏,玩家属性修改不频繁,也不需要跨多个模块共享状态——继续用Struct完全没问题,值类型的线程安全、状态可控这些优点会帮你避免很多潜在bug。
- 如果是复杂游戏(比如联网多人、多模块同步状态),或者需要继承扩展——把
Player换成Class,Game可以根据是否需要共享实例来决定,要是整个游戏状态需要多地方共享,也可以换成Class。
总的来说,Swift推荐优先用值类型,但不是教条。如果只是因为“修改属性麻烦”就换Class,有点小题大做,先试试上面的优雅写法,真碰到值类型解决不了的场景再换也不迟~
内容的提问来源于stack exchange,提问作者MDMonty
相关产品推荐
相关产品推荐

