如何在多个视图中重复使用同一个 FetchRequest,而不是同一个请求?

How to re-use the same FetchRequest, rather than the same request in several views?

我在 ContentView 下的多个顶级视图中使用相同的提取请求。我的意思是相同的实体/谓词等

之前我尝试在 ContentView 中执行一次请求,然后将其作为数组传递给多个视图层。但是,这会阻止更改、删除等在其他视图中传播。

我只是想知道是否还有其他可行的方法?

我认为某种单例方法可能会奏效,但我担心性能影响,但是这可能比必须多次 运行 请求更重要。

另外,我想知道传递请求结果而不是数组? 然而不得不传递这个似乎很难看。

您可以使用 Environment 将您的模型传递给 children,而无需将数组传递给多个视图层。您首先要创建自己的 EnvirnomentKey

public struct ModelEnvironmentKey: EnvironmentKey {
    public static var defaultValue: [Model] = []
}

public extension EnvironmentValues {
    var models: [Model] {
        get { self[ModelEnvironmentKey] }
        set { self[ModelEnvironmentKey] = newValue }
    }
}

public extension View {
    func setModels(_ models: [Model]) -> some View {
        environment(\.models,  models)
    }
}

我喜欢使用 ViewModifiers 来设置我的环境,遵循 Single-Responsibility 原则:

struct ModelsLoaderViewModifier: ViewModifier {
    @FetchRequest(entity: Model(), sortDescriptors: [])
    var models: FetchedResults<Model>
    
    func body(content: Content) -> some View {
        content
            .setModels(Array(models))
    }
}

extension View {
    func loadModels() -> some View {
        modifier(ModelsLoaderViewModifier)
    }
}

然后我会将此修饰符添加到视图层次结构的相当高的位置。

@main
struct BudgetApp: App {
    @ObservedObject var persistenceManager = PersistenceManager(usage: .main)
    let startup = Startup()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .loadModels()
        }
    }
}

现在ContentView可以从环境中读取:

struct ContentView: View {
    @Environment(\.models) var models
    
    var body: some View {
        List {
            ForEach(models) { model in
                Text(model.name)
            }
        }
    }
}