TestFlight构建中SwiftData嵌套@Model排序崩溃问题
SwiftData嵌套模型排序在TestFlight构建中崩溃的解决方案
问题重现
SwiftData模型代码
@Model class ClosedDealModelContainer { var closedDeal: ClosedDealModel init(closedDeal: ClosedDealModel) { self.closedDeal = closedDeal } } @Model public class ClosedDealModel: Hashable { public enum DealType: Codable { case long case short } public let id: String public let userId: String public var buy: BuyModel public var sell: SellModel public var type: DealType public var symbol: String public var currency: String public init( id: String, buy: BuyModel, sell: SellModel, type: DealType, symbol: String, userId: String, currency: String ) { self.id = id self.buy = buy self.sell = sell self.type = type self.symbol = symbol self.userId = userId self.currency = currency } } @Model public class BuyModel { public let fee: Double public let date: Date public let price: Double public let count: Double public init(fee: Double, date: Date, price: Double, count: Double) { self.fee = fee self.date = date self.price = price self.count = count } } @Model public class SellModel: Equatable { public let fee: Double public let date: Date public let price: Double public let count: Double public init(fee: Double, date: Date, price: Double, count: Double) { self.fee = fee self.date = date self.price = price self.count = count } }
查询代码
let descriptor = FetchDescriptor<ClosedDealModelContainer>( predicate: #Predicate { container in container.closedDeal.userId == userId }, sortBy: [SortDescriptor(\.closedDeal.sell.date)] ) let items = try modelContext?.fetch(descriptor)
崩溃情况
- Debug/本地Release版本运行正常
- TestFlight构建中在
static PersistentModel.keyPathToString(keypath:)行崩溃 - 改为按
ClosedDealModel.id排序可正常运行,问题锁定在嵌套对象的键路径解析
问题原因
TestFlight默认使用Fastest, Smallest [-Os]全优化编译,该优化会剥离SwiftData解析嵌套键路径所需的元数据,导致keyPathToString无法正确识别跨多个@Model实体的嵌套路径。Debug模式下优化关闭,元数据完整,因此不会崩溃。
解决方案
方案1:添加顶层计算属性(推荐)
在ClosedDealModelContainer中新增直接映射嵌套属性的计算属性,通过顶层属性排序绕过嵌套键路径解析:
@Model class ClosedDealModelContainer { var closedDeal: ClosedDealModel // 新增计算属性,直接返回嵌套的销售日期 var sellDate: Date { closedDeal.sell.date } init(closedDeal: ClosedDealModel) { self.closedDeal = closedDeal } }
修改查询代码,改用顶层计算属性排序:
let descriptor = FetchDescriptor<ClosedDealModelContainer>( predicate: #Predicate { container in container.closedDeal.userId == userId }, sortBy: [SortDescriptor(\.sellDate)] )
方案2:调整编译优化级别(临时方案)
在Target的Build Settings中,将TestFlight对应的Build Configuration的Optimization Level改为Fastest [-O],或关闭Whole Module Optimization。该方法会降低部分性能优化,仅作为临时过渡方案使用。
方案3:手动指定字符串键路径(不推荐)
绕过键路径自动解析,手动传入字符串形式的路径。注意该方法依赖SwiftData内部路径格式,版本更新可能失效:
let descriptor = FetchDescriptor<ClosedDealModelContainer>( predicate: #Predicate { container in container.closedDeal.userId == userId }, sortBy: [SortDescriptor(\ClosedDealModelContainer.closedDeal.sell.date, keyPathString: "closedDeal.sell.date")] )
内容的提问来源于stack exchange,提问作者Igor Ševtšenko
相关产品推荐
相关产品推荐

