SwiftUI中如何基于父视图传入元素属性用NSPredicate过滤@FetchRequest?
解决SwiftUI中通过父视图属性过滤@FetchRequest的问题
问题场景
我有一组Core Data的Contract实体,每个Contract关联一组Invoice实体,且Contract拥有唯一的序列号属性。在Content View中通过@FetchRequest获取所有Contract生成列表,点击列表项通过NavigationLink跳转到子视图并传入对应的Contract实例。当前子视图无法实时显示新增的Invoice,只有返回Content View再重新进入才会刷新;尝试用传入的Contract序列号过滤@FetchRequest时,遇到报错:
Cannot use instance member 'aContract' within property initializer; property initializers run before 'self' is available
解决方案
方案1:直接利用Core Data关联关系(推荐)
既然已经传入完整的Contract实例,无需重新Fetch,直接使用其关联的Invoice集合即可。Core Data的关联关系默认支持动态更新,只要关联配置正确,新增Invoice后视图会自动刷新。
代码示例:
struct InvoiceDetailView: View { // 用@ObservedObject监听Contract实例的变化 @ObservedObject var contract: Contract var body: some View { List { // 将Core Data的NSSet关联属性转为数组遍历 ForEach(contract.invoiceArray?.allObjects as? [Invoice] ?? []) { invoice in Text(invoice.invoiceIdentificationAttribute ?? "无编号") } } .navigationTitle(contract.contractSerialNumber ?? "合同详情") } }
注意:需确保Core Data中Contract与Invoice的关联关系配置正确,invoiceArray是Contract实体对应的To-Many关联属性(Xcode自动生成的类中默认是NSSet?类型,需转成数组使用)。
方案2:动态初始化@FetchRequest(适用于需要重新过滤的场景)
如果必须通过传入的属性动态创建@FetchRequest,可以通过初始化方法设置predicate,避开属性初始化时无法访问self的限制。
代码示例:
struct ContractInvoiceView: View { let contractSerialNumber: String @FetchRequest var contracts: FetchedResults<Contract> // 在初始化方法中动态配置FetchRequest init(contractSerialNumber: String) { self.contractSerialNumber = contractSerialNumber _contracts = FetchRequest( sortDescriptors: [], predicate: NSPredicate(format: "contractSerialNumber == %@", contractSerialNumber) ) } var body: some View { List { // 利用唯一序列号取第一个匹配的Contract if let contract = contracts.first { ForEach(contract.invoiceArray?.allObjects as? [Invoice] ?? []) { invoice in Text(invoice.invoiceIdentificationAttribute ?? "无编号") } } } .navigationTitle("发票列表") } }
内容的提问来源于stack exchange,提问作者Andrei M.
相关产品推荐
相关产品推荐

