gpt4 book ai didi

SwiftUI:ObservableObject 在重绘时不会保持其状态

转载 作者:行者123 更新时间:2023-12-03 09:16:41 25 4
gpt4 key购买 nike

问题

为了实现应用程序代码的简洁外观,我为每个包含逻辑的 View 创建了 ViewModel。

一个普通的 ViewModel 看起来有点像这样:

class SomeViewModel: ObservableObject {

@Published var state = 1

// Logic and calls of Business Logic goes here
}

并像这样使用:
struct SomeView: View {

@ObservedObject var viewModel = SomeViewModel()

var body: some View {
// Code to read and write the State goes here
}
}

当 Views Parent 没有被更新时,这可以正常工作。如果父级的状态发生变化,这个 View 会被重绘(在声明性框架中很正常)。 但是 ViewModel 也被重新创建,之后不再保存状态。与其他框架(例如:Flutter)相比,这是不寻常的。

在我看来,ViewModel 应该保留,或者 State 应该保留。

如果我用 @State 替换 ViewModel属性(property)和使用 int (在本例中)直接保持不变, 不会重新创建 :
struct SomeView: View {

@State var state = 1

var body: some View {
// Code to read and write the State goes here
}
}

这显然不适用于更复杂的国家。如果我为 @State 设置一个类(如 ViewModel)越来越多的事情没有按预期工作。

问题
  • 有没有办法不每次都重新创建 ViewModel?
  • 有没有办法复制 @State @ObservedObject 的属性包装器?
  • 为什么@State 将状态保留在重绘上?

  • 我知道通常在内部 View 中创建 ViewModel 是不好的做法,但是可以通过使用 NavigationLink 或 Sheet 来复制这种行为。
    有时,当您想到一个非常复杂的 TableView 时,将 State 保留在 ParentsViewModel 中并使用绑定(bind)是没有用的,其中 Cell 本身包含很多逻辑。
    对于个别情况,总有一种解决方法,但我认为如果不重新创建 ViewModel 会更容易。

    重复的问题

    我知道有很多关于这个问题的问题,都在谈论非常具体的用例。在这里我想谈谈一般问题,而不是太深入地讨论自定义解决方案。

    编辑(添加更详细的示例)

    当拥有一个改变状态的 ParentView 时,比如来自数据库、API 或缓存的列表(想想一些简单的事情)。通过 NavigationLink您可能会到达一个详细信息页面,您可以在其中修改数据。通过更改数据,响应式(Reactive)/声明式模式会告诉我们也更新 ListView,然后它会“重绘” NavigationLink。 ,这将导致 ViewModel 的重新创建。

    我知道我可以将 ViewModel 存储在 ParentView/ParentView 的 ViewModel 中,但这是 IMO 的错误做法。而且由于订阅被销毁和/或重新创建 - 可能会有一些副作用。

    最佳答案

    最后,苹果提供了一个解决方案:@StateObject .
    通过替换 @ObservedObject@StateObject我最初的帖子中提到的一切都有效。
    不幸的是,这仅在 ios 14+ 中可用。
    这是我的 Xcode 12 Beta 代码(2020 年 6 月 23 日发布)

    struct ContentView: View {

    @State var title = 0

    var body: some View {
    NavigationView {
    VStack {
    Button("Test") {
    self.title = Int.random(in: 0...1000)
    }

    TestView1()

    TestView2()
    }
    .navigationTitle("\(self.title)")
    }
    }
    }

    struct TestView1: View {

    @ObservedObject var model = ViewModel()

    var body: some View {
    VStack {
    Button("Test1: \(self.model.title)") {
    self.model.title += 1
    }
    }
    }
    }

    class ViewModel: ObservableObject {

    @Published var title = 0
    }

    struct TestView2: View {

    @StateObject var model = ViewModel()

    var body: some View {
    VStack {
    Button("StateObject: \(self.model.title)") {
    self.model.title += 1
    }
    }
    }
    }
    如您所见, StateObject在重绘父 View 时保持它的值(value),而 ObservedObject正在重置。

    关于SwiftUI:ObservableObject 在重绘时不会保持其状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61676823/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com