【问题标题】:WatchOS Using ObservableObject in Conditional in View Causing Runtime ErrorWatchOS 在条件视图中使用 ObservableObject 导致运行时错误
【发布时间】:2021-11-18 16:10:50
【问题描述】:

我使用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 弹出错误。

【问题讨论】:

  • 切换模式与多页面视图不同。此外,如果您在视图中初始化观察到的对象,则应该使用状态对象。但在这种情况下,只是不要在切换中初始化,从多页面视图中获取它作为参数
  • 我稍微更新了代码,因为我使用的是 .shared 单例,而不是新实例。但是,我根据您的建议对其进行了更改,并且只有轻微的改进。错误仍然存​​在。
  • 哪一行出现错误?
  • 那是疯狂的部分。它不与实际项目或 MRE 的任何行相关联。我有一个线程跟踪,但我在符号化它时遇到了问题。我提出了一个关于使用 otool 获取 ASLR 幻灯片的问题,但没有得到任何回应。我通过消除过程走到了这一步,MRE 确认​​这与视图中的条件在视图之外被更改有关。 Runtime Error 断点在@main 处无用地停止,并且跟踪没有帮助。

标签: swift swiftui state watchos tabview


【解决方案1】:

我很长一段时间都遇到同样的问题,并且在 Xcode 13.2.1 上仍然发生这种情况。

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

解决方案是使用TabView 的初始化程序,其值为selectioninit(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 属性,并在两个TabViews 上使用它(使用单独的属性也可以)。

【讨论】:

  • 你是怎么遇到这个解决方案的?奇迹般有效!我会把它拿回来看看它在生产应用程序中是如何工作的,但是谢谢!
  • 天才,错误消失了。感谢您的解决方案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-22
  • 1970-01-01
  • 1970-01-01
  • 2018-02-18
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多