在SwiftUI函数中使用@FetchRequest触发StateObject访问错误
问题解决:SwiftUI动态@FetchRequest导致的StateObject错误
错误原因
你把@FetchRequest放在函数内部使用是完全错误的——@FetchRequest这类属性包装器必须作为视图结构体的存储属性存在,放在函数里会导致SwiftUI无法正确管理其底层依赖的StateObject生命周期,从而触发Accessing StateObject's object without being installed on a View运行时错误。
同时你的代码还有两个潜在问题:
compartment属性设置了无意义的默认值= Compartment(),它应该由前一个视图传入,不需要默认值- 用
compartment.name作为谓词匹配条件存在风险,Core Data中关联对象应该直接用对象引用而非属性值(避免名称重复导致数据错误)
正确实现代码
import SwiftUI import CoreData struct CompartmentDetailView: View { @Environment(\.managedObjectContext) private var viewContext let compartment: Compartment // 由前一个视图传入,无默认值 // 动态初始化的@FetchRequest,关联当前compartment的库存 @FetchRequest private var inventories: FetchedResults<Inventory> // 自定义初始化器,根据传入的compartment设置查询谓词 init(compartment: Compartment) { self.compartment = compartment // 直接用compartment对象作为谓词条件,符合Core Data关联规范 let predicate = NSPredicate(format: "compartment == %@", compartment) _inventories = FetchRequest( sortDescriptors: [NSSortDescriptor(keyPath: \Inventory.name, ascending: true)], predicate: predicate, animation: .default ) } var body: some View { ScrollView { NavigationView { List { ForEach(inventories) { inventory in NavigationLink( destination: InventoryDetailView(inventory: inventory) ) { HStack(spacing: 20.0) { Text(inventory.name ?? "") .font(.headline) } } } } } } .padding(.top, 30) .navigationTitle(compartment.name ?? "") } }
关键说明
- @FetchRequest的正确位置:必须作为视图的存储属性,通过自定义初始化器动态传入谓词,SwiftUI会自动管理其生命周期和视图更新
- 谓词的正确写法:用
compartment对象直接匹配而非name属性,既保证数据准确性,又符合Core Data对象关联的设计逻辑 - 处理可选值:Core Data实体的属性通常是可选类型,所以用
?? ""处理name的nil情况,避免运行时崩溃
内容的提问来源于stack exchange,提问作者Peel
相关产品推荐
相关产品推荐

