WatchOS 在条件视图中使用 ObservableObject 导致运行时错误
Posted
技术标签:
【中文标题】WatchOS 在条件视图中使用 ObservableObject 导致运行时错误【英文标题】:WatchOS Using ObservableObject in Conditional in View Causing Runtime Error 【发布时间】: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
,但ViewTwo
和ViewThree
相同,但文字不同:
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
处无用地停止,并且跟踪没有帮助。
【参考方案1】:
我很长一段时间都遇到同样的问题,并且在 Xcode 13.2.1 上仍然发生这种情况。
似乎是 watchOS 上的 TabView
存在问题,因为如果您将 TabView 替换为另一个 View,错误就会消失。
解决方案是使用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
属性,并在两个TabViews 上使用它(使用单独的属性也可以)。
【讨论】:
你是怎么遇到这个解决方案的?奇迹般有效!我会把它拿回来看看它在生产应用程序中是如何工作的,但是谢谢! 天才,错误消失了。感谢您的解决方案以上是关于WatchOS 在条件视图中使用 ObservableObject 导致运行时错误的主要内容,如果未能解决你的问题,请参考以下文章
如何在 WatchOS 中使用背景视图填充整个 Button 区域?