Swift中使用TaskGroup并发加载数据时修改Game结构体的问题
问题解决:Swift异步加载结构体关联对象的正确方式
错误原因
- Game是值类型(结构体),for-in循环中遍历的
game默认是let常量,无法直接修改其属性,这就是报错“game is let constant”的核心原因。 - 原代码为每个Game创建两个独立任务,最终会得到两个仅修改了单个字段的Game实例,导致结果数组包含重复的不完整数据,不符合业务需求。
正确实现
为每个Game单独创建一个任务,在任务内部并发加载所有关联对象,通过复制原结构体并修改属性生成完整实例(值类型推荐通过创建新实例修改,而非修改原常量)。
修正后的代码:
struct Game: Codable { var field1: Int var field2: Int var field1Object: Object1? var field2Object: Object2? // 其他字段... } func fetchData(_ games: [Game]) async -> [Game] { await withTaskGroup(of: Game.self) { group in // 为每个Game创建一个独立任务 for game in games { group.addTask { // 并发加载两个关联对象,提升执行效率 async let loadedObj1 = loadObjectBy(game.field1) async let loadedObj2 = loadObjectBy(game.field2) // 等待两个加载任务完成 let obj1 = await loadedObj1 let obj2 = await loadedObj2 // 复制原Game为可变变量,设置加载后的关联对象 var updatedGame = game updatedGame.field1Object = obj1 updatedGame.field2Object = obj2 return updatedGame } } // 收集所有完成的完整Game实例 var updatedGames = [Game]() updatedGames.reserveCapacity(games.count) for await completedGame in group { updatedGames.append(completedGame) } return updatedGames } }
关键说明
- 使用
async let实现两个关联对象的并发加载,比顺序等待更高效。 - 结构体是值类型,通过
var updatedGame = game复制原实例,再修改属性,避免直接修改let常量的问题。 - 每个Game对应一个任务,最终结果数组中的每个元素都是完整的Game实例,不会出现重复或数据缺失。
内容的提问来源于stack exchange,提问作者ArisRS
相关产品推荐
相关产品推荐

