SwiftUI:基于环境初始化ObservableObject

2024-03-08

在此示例中,蓝色矩形最初应在具有以下功能的设备上可见:.regular尺寸类别并隐藏在具有.compact尺寸等级。

我正在使用一个ObservableObject called Settings@Published多变的isVisible管理矩形的可见性。我的问题是我不知道如何初始化Settings与正确的horizontalSizeClass从我的ContentView。现在我正在使用.onAppear改变的值isVisible但这会触发.onReceive。在紧凑型设备上,这会导致矩形在视图呈现时可见并淡出,而不是立即不可见。

我怎样才能初始化Settings基于环境值,例如horizontalSizeClass以便isVisible从一开始就是正确的吗?

struct ContentView: View {
    @Environment(\.horizontalSizeClass) var horizontalSizeClass
    @StateObject var settings = Settings()
    @State var opacity: CGFloat = 1

    var body: some View {
        VStack {
            Button("Toggle Visibility") {
                settings.isVisible.toggle()
            }
            .onReceive(settings.$isVisible) { _ in
                withAnimation(.linear(duration: 2.0)) {
                    opacity = settings.isVisible ? 1 : 0
                }
            }
            Rectangle()
                .frame(width: 100, height: 100)
                .foregroundColor(.blue)
                .opacity(opacity)
        }
        .onAppear {
            settings.isVisible = horizontalSizeClass == .regular // too late
        }
    }
}

class Settings: ObservableObject {
    @Published var isVisible: Bool = true // can't get size class here
}

矩形在开始时不应该是可见的:


我们只需要执行依赖注入(已知环境是父环境,因此可以轻松注入子环境),并且使用内部视图很简单,例如

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

    struct MainView: View {
        // later knonw injection
        @EnvironmentObject var settings: Settings

        var body: some View {
            VStack {
                Button("Toggle Visibility") {
                    settings.isVisible.toggle()
                }
                Rectangle()
                    .frame(width: 100, height: 100)
                    .foregroundColor(.blue)
                    .opacity(settings.isVisible ? 1 : 0) // << direct dependency !!
            }
            .animation(.linear(duration: 2.0), value: settings.isVisible) // << explicit animation
        }
    }

    var body: some View {
        MainView()          // << internal view
            .environmentObject(
                Settings(isVisible: horizontalSizeClass == .regular) // << initial injecttion !!
            )
    }
}

使用 Xcode 13.4 / iOS 15.5 进行测试

测试代码在这里 https://github.com/Asperi-Demo/4SwiftUI/blob/master/PlayOn_iOS/PlayOn_iOS/Findings/TestEnvironmentDepenencyInjectionIinternalView.swift

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SwiftUI:基于环境初始化ObservableObject 的相关文章

随机推荐