如何将 @FetchRequest 属性包装器的新 nsPredicate 动态属性与传递到 View 的对象一起使用

问题描述 投票:0回答:2

我的第一次尝试是在

nsPredicate
中设置属性包装器的
.onAppear
动态属性,但如果视图因任何原因重新初始化,由
.onAppear
设置的谓词就会丢失。所以我又重新使用 init 模式。

这是我认为应该起作用(但不起作用)和确实起作用(无论多么神秘)的东西:

struct ItemEditView : View {
    
    var item: Item
    
    @FetchRequest(fetchRequest: Attribute.fetchRequestAllInOrder(), animation: .default)
    var attributes: FetchedResults<Attribute>

    init(item: Item) {
        self.item = item
        
        // This is how I would have expected to set the dynamic property at View initialization, however
        // it crashes on this statement
        attributes.nsPredicate = NSPredicate(format: "item == %@", item)
        
        // Not sure why the below works and the above does not.
        // It seems to work as desired, however it receives this runtime warning:
        // "Context in environment is not connected to a persistent store coordinator"
        $attributes.projectedValue.wrappedValue.nsPredicate = NSPredicate(format: "item == %@", item)
    }
    
    var body: some View {
        List {
            ForEach(attributes) { attribute in
                Text("Name:\(attribute.name) Order:\(attribute.order)")
            }
        }
    }
}

那么,为什么第一次对 nsPredicate 的赋值会崩溃呢?注释掉第一个之后,为什么第二个有效?警告消息是真正的问题吗?有一个更好的方法吗?似乎应该有一种简单的方法可以使用新的动态属性来做到这一点。

core-data swiftui nspredicate
2个回答
1
投票

事实证明,(重新)设置

nsPredicate
@FetchRequest
onAppear
属性确实是正确的方法。但是,要实现此功能,您必须确保在调用
init()
后不会再次调用 View 的
onAppear
方法。今年 WWDC (WWDC21-10022) 的 Demystify SwiftUI 会议上有一些关于如何实现这一目标的宝贵提示。


0
投票

FetchRequest
是仅在调用
DynamicProperty
之前准备就绪的
body
。如果您自己实现
DynamicProperty
,您将看到
update
函数,它是从
managedObjectContext
获取
@Environment
的地方,并且直到调用
body
之前环境才准备好。

实现同样目标的另一种方法是:

struct ItemEditView : View {
    
    let item: Item
    
    var request: FetchRequest(predicate: NSPredicate(value: false))
    var results: FetchedResults<Attribute> {
        request.wrappedValue.nsPredicate = NSPredicate(format: "item == %@", item)
        request.wrappedValue.sortDescriptors = ...
        return request.wrappedValue
    }

© www.soinside.com 2019 - 2024. All rights reserved.