WatchOS 在有条件的视图中使用 ObservableObject 导致运行时错误

WatchOS Using ObservableObject in Conditional in View Causing Runtime Error

我用一个ObservableObject来保持用户是否订阅我的应用程序的状态,并根据订阅状态显示不同的视图。这在 Xcode 13 和 WatchOS 8 之前工作正常,但现在这会导致运行时错误 runtime: SwiftUI: Accessing State's value outside of being installed on a View. This will result in a constant Binding of the initial value and will not update. 并且,绑定不会根据错误更新。这发生在 Xcode 13.1 和 13.2b2

下面的代码重现了错误:

struct MultiPageView: View {
    @ObservedObject var subscribed = SubscribedModel.shared
    
    var body: some View {
        if subscribed.value {
            TabView {
                ViewOne()
                ViewTwo()
                ViewThree()
                ToggleView()
            }
            .tabViewStyle(PageTabViewStyle())
        } else {
            TabView {
                ViewOne()
                ToggleView()
            }
            .tabViewStyle(PageTabViewStyle())
        }
    }
}

struct ToggleView: View {
    @ObservedObject var subscribed = SubscribedModel()

    var body: some View {
        Toggle(isOn: $subscribed.value) {
            Text("Subscribed")
        }
    }
}

class SubscribedModel: ObservableObject {
    public static let shared = SubscribedModel.shared
    
    @Published var value: Bool = false
}

为了简洁起见,我只列出 ViewOne,但是 ViewTwoViewThree 是相同的,只是不同的文本:

struct ViewOne: View {
    var body: some View {
        Text("View One")
            .padding()
    }
}

如果您导航到 ToggleView(),然后切换开关,错误会立即弹出。有什么解决这个问题的建议吗?

根据@LoremIpsum 评论更新:

struct MultiPageView: View {
    @StateObject var subscribed = SubscribedModel()
    
    var body: some View {
        if subscribed.value {
            TabView {
                ViewOne()
                ViewTwo()
                ViewThree()
                ToggleView(subscribed: $subscribed.value)
            }
            .tabViewStyle(PageTabViewStyle())
        } else {
            TabView {
                ViewOne()
                ToggleView(subscribed: $subscribed.value)
            }
            .tabViewStyle(PageTabViewStyle())
        }
    }
}

struct ToggleView: View {
    @Binding var subscribed: Bool

    var body: some View {
        Toggle(isOn: $subscribed) {
            Text("Subscribed")
        }
    }
}

现在正在TabViews之间切换,但错误仍然存​​在,并且立即出现。删除了 DerivedData 并清理了构建文件夹。有什么想法吗?

我要补充一点,同样的基本代码在 iOS 15 上 运行 没问题。只是 WatchOS 弹出错误。

我遇到同样的问题很长时间了,在 Xcode 13.2.1.

上仍然发生这种情况

watchOS 上的 TabView 似乎是一个问题,因为如果您将 TabView 替换为另一个视图,错误就会消失。

解决方案是使用 TabView 的初始化程序和 selection 值:init(selection:content:)

1定义一个属性供选择

@State private var selection = 0

2 更新 TabView

来自

TabView {
    // content
}

TabView(selection: $selection) {
    // content
}

更新您的代码如下所示:

struct MultiPageView: View {
    @StateObject var subscribed = SubscribedModel()
    @State private var selection = 0
    
    var body: some View {
        if subscribed.value {
            TabView(selection: $selection) {
                ViewOne()
                ViewTwo()
                ViewThree()
                ToggleView(subscribed: $subscribed.value)
            }
            .tabViewStyle(PageTabViewStyle())
        } else {
            TabView(selection: $selection) {
                ViewOne()
                ToggleView(subscribed: $subscribed.value)
            }
            .tabViewStyle(PageTabViewStyle())
        }
    }
}

基本上只是为 TabView.selection 定义一个 @State 属性,然后在你的两个 TabView 上使用它(使用分离的属性也可以)。