如何创建一个没有默认值的环境,以便在未提供的情况下使用时会抛出异常

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

我试图要求提供

thing
,而不是使用
defaultValue = Thing()
作为默认值提供。 如果我使用 Thing? 将环境设置为可选,那么我必须在每个视图中展开它。 如果没有这种方法,当我需要传递特定实例时,我的初始化程序似乎总是被调用两次。

我正在尝试使用下面的代码,但它一运行就会抛出致命的“未提供东西”。 不过,我在 thingApp 中提供环境,所以我很困惑为什么会发生这种情况。 即使不使用

@Environment(\.thing) var thing
也会发生。

import SwiftUI

@main
struct thingApp: App {
    var thing = Thing()

    var body: some Scene {
        WindowGroup {
            ContentView().environment(\.thing, thing)
        }
    }
}

struct ContentView: View {
    @Environment(\.thing) var thing

    var body: some View {
        Text("count: \(self.thing.count)")
    }
}

@MainActor
@Observable class Thing {
    var count: Int = 3

    func inc() {
        self.count = self.count + 1
    }
}

private struct ThingKey: EnvironmentKey {
    static var defaultValue: Thing {
        fatalError("Thing not provided")
    }
}

extension EnvironmentValues {
    var thing: Thing {
        get { self[ThingKey.self] }
        set { self[ThingKey.self] = newValue }
    }
}
swift swiftui
1个回答
0
投票

崩溃的原因是,在您的情况下,SwiftUI 在通过关键路径写入环境值时首先读取环境值。

但即使事实并非如此: 根据定义,自定义 EnvironmentKey 实现必须实现默认值,因为如果未在视图上显式设置或覆盖该值,则应该能够检索它们。

作为旁注,使用 Entry 宏可以有更短的语法:

extension EnvironmentValues {
    @Entry var thing: Thing = /* your default value */
}

但是,您可以使用不同的方法来获得您想要的行为:

import SwiftUI

@main
struct thingApp: App {
    var thing = Thing()

    var body: some Scene {
        WindowGroup {
            ContentView().environment(thing)
        }
    }
}

struct ContentView: View {
    @Environment(Thing.self) var thing

    var body: some View {
        Text("count: \(self.thing.count)")
    }
}

@MainActor
@Observable class Thing {
    var count: Int = 3

    func inc() {
        self.count = self.count + 1
    }
}

如果环境中没有该类型的对象,此方法将抛出异常。

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