SwiftUI & CoreData:向子视图传FetchedResults子属性Release模式EXC_BAD_ACCESS错误
问题原因
这个问题是Core Data的*Faulting(故障)*机制与Release模式下编译器内存优化共同导致的:
- 你通过关系获取的
wPersonScores、wScoreTemplate默认都是Fault对象,只有首次访问属性时才会从持久化存储加载完整数据 - Debug模式下编译器不会做激进的内存释放优化,临时创建的Fault对象会被暂时保留;但Release模式下,你直接把遍历得到的
personScore、跨关系读取的scoreTemplate直接传给子视图时,这些临时Fault对象没有被强引用持有,会被提前释放,导致子视图访问属性时触发野指针崩溃,错误码257就是典型的Core Data对象提前释放的错误码。
具体修复方案
可按以下步骤依次验证:
- 方案1:遍历的时候主动触发Fault加载,保证对象被完整初始化后再传递
修改V_SessionDetail里的ForEach逻辑:
ForEach(Array(scoreSession.wPersonScores.enumerated()), id: \.element) { (i, personScore) in // 主动访问一次属性触发Fault加载,避免对象被提前释放 let _ = personScore.score let scoreTemplate = scoreSession.wGame.wScoreTemplate let _ = scoreTemplate.wName // 随便访问对象的任意属性即可 V_ScoreCard( scoreTemplate: scoreTemplate, personScore: personScore ) }
- 方案2:修改Core Data关系的修饰规则
在Core Data模型编辑器里,把M_ScoreSession到wPersonScores、M_Game到wScoreTemplate的关系的*Optional(可选)*勾选去掉,或者在代码的关系属性定义处用强类型集合,避免自动释放:
// M_ScoreSession的wPersonScores属性定义修改为非可选的具体类型集合 @NSManaged public var wPersonScores: Set<M_PersonScore>
- 方案3:子视图改用@StateObject接收(iOS14+可用)
如果部署目标在iOS14及以上,把V_ScoreCard里的@ObservedObject改成@StateObject,保证子视图自身强持有传入的ManagedObject:
struct V_ScoreCard: View { @StateObject var personScore: M_PersonScore @StateObject var scoreTemplate: M_ScoreTemplate // 其余代码保持不变 }
修改后切换到Release模式编译,按复现步骤操作即可验证修复效果。
内容的提问来源于stack exchange,提问作者fer0n
相关产品推荐
相关产品推荐

