SwiftUI 视图中的 onReceive 导致无限循环
Posted
技术标签:
【中文标题】SwiftUI 视图中的 onReceive 导致无限循环【英文标题】:onReceive in SwiftUI view causes infinite loop 【发布时间】:2020-05-07 21:52:26 【问题描述】:在一个 SwiftUI 应用程序中,我有一个 ObservableObject
来跟踪用户设置:
class UserSettings: ObservableObject
@Published var setting: String?
我有一个视图模型来控制我的视图的状态:
class TestViewModel: ObservableObject
@Published var state: String = ""
我有我的看法。当用户设置改变时,我想让视图模型更新视图的状态:
struct HomeView: View
@EnvironmentObject var userSettings: UserSettings
@ObservedObject var viewModel = TestViewModel()
var body: some View
Text(viewModel.state)
.onReceive(userSettings.$setting) setting in
self.viewModel.state = setting
当UserSettings.setting
在另一个视图中更改时,它会导致我视图上的onReceive
在无限循环中被调用,我不明白为什么。我看到了this question,这个循环对我来说很有意义,因为观察到的ObservableObject
的状态会随着观察而改变。
但是,在我的情况下,我没有更改观察到的对象(环境对象)状态。我正在观察环境对象并更改重绘视图的视图模型状态。
视图是否重绘了导致问题的原因?每次重绘视图时都会调用onReceive
吗?
有没有更好的方法来完成我想做的事情?
编辑:这是我的问题的一个大大简化的版本。在我的应用程序中,视图模型负责根据用户的设置执行网络请求并更新视图的状态,例如显示错误消息或加载指示器。
【问题讨论】:
【参考方案1】:从所描述的场景中,我看不到在视图模型中重复设置的原因。可以直接从userSettings
显示值,如
struct HomeView: View
@EnvironmentObject var userSettings: UserSettings
@ObservedObject var viewModel = TestViewModel()
var body: some View
Text(userSettings.setting)
【讨论】:
感谢您抽出宝贵时间回答,但正如我在对问题的编辑中解释的那样,我确实需要设置 viewModel。在我的应用程序中,我需要调用视图模型中的一个函数来执行网络请求,并且视图模型会在请求执行时设置视图的状态(例如显示错误消息、加载指示器等) 你能想到为什么会发生循环行为吗?这对我来说是真正令人头疼的事情。 @gnarlybracket,关于简化问题的简化答案,因为我没有看到你需要自己推断的真实代码 - 逻辑中的循环,而不是 swiftui - 解决方案,如图所示,打破它。【参考方案2】:每当您有一个带有 @ObservedObject 的 onReceive 设置另一个(或相同)@ObservedObject 的已发布值时,如果这些已发布的属性以某种方式显示,您就有创建无限循环的风险。
让你的 onReceive 验证接收到的值实际上是在更新一个值,而不仅仅是设置相同的值,否则它将无限设置/重绘。在这种情况下,例如:
.onReceive(userSettings.$setting) setting in
if setting != self.viewModel.state
self.viewModel.state = setting
【讨论】:
谢谢!!!这实际上是唯一让我的代码正常工作的事情。你是个传奇!!【参考方案3】:您可以通过将@ObservedObject 切换为@StateObject 来防止无限地重新渲染视图主体。
【讨论】:
以上是关于SwiftUI 视图中的 onReceive 导致无限循环的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI视图onReceive方法接收“冗余”事件的解决
当 ObservedObject 更改时,在 SwiftUI 视图中未调用 onReceive
如何在 onReceive 计时器关闭 SwiftUI iOS 中导航另一个视图
SwiftUI onReceive 不适用于 UIPasteboard 发布者
SwiftUI:输入字段键盘动画导致选项卡视图中的其他视图动画
当 Publisher 参数没有要发出的任何新值时,为啥会调用 SwiftUI View 上的 onReceive 块?