ios - 如何在 SwiftUI 中通过 ViewModel 传播模型更改?

标签 ios mvvm swiftui

我试图了解 SwiftUI 中的 MVVM 模式,但我并不完全了解 ViewModel 如何监听和传播来自 Model 对象的更改。许多示例,包括 this one来自 Apple,谈论让模型继承自 ObservableObject 并直接在您的 View 中使用它。这是有道理的。

但是 ViewModel 应该观察其基础模型的变化的最佳/推荐方式是什么?

一个简单的例子是一个WidgetView,它显示一个小部件的title,但是title可以在后台网络中改变打电话,例如。

class WidgetView: View {
    @ObservedObject var widgetVM = WidgetViewModel()

    var body: some View {
        Text(widgetVM.title)
    }
}

class WidgetViewModel : ObservableObject {
   var widget: Widget

   var title: String {
      get {
         // Some translation to the title for this particular view
         return widget.title + "!"
      }
   }
}

struct Widget {
    // Some other timer or background process is changing the title
    var title: String
}

我探索过的一个粗略的解决方案是有一个单独的 title 并监听变化。因此,如果 Widget 扩展了 ObservableObject@Published title 字段,那么 WidgetViewModel可以执行以下操作:

class WidgetViewModel : ObservableObject {
   var widget: Widget

   @Published var title: String = ""
   var cancellable: AnyCancellable?

   init() {
       self.cancellable = widget.$title.receive(on: DispatchQueue.main)
           .sink(receiveValue: self.updateTitle )
   }

   func updateTitle(_: String) {
       self.title = widget.title + "!"
   }
}

Widget 是否也推荐/标准扩展 ObservableObject?如果是这样,WidgetViewModel 如何正确传递更改通知?看起来 WidgetModelView.widget 需要同时是 @Published 和 @ObservedObject,但这似乎不对。

有人对此有任何见解吗?

最佳答案

您的 Widget 是结构体,因此它不能是 ObservableObject,您可以执行以下操作

class WidgetViewModel : ObservableObject {

   var widget: Widget {
     didSet {
        updateTitle(widget)    // << here !!
     }
   }

   @Published var title: String = ""

   func updateTitle(_: String) {
       self.title = widget.title + "!"
   }
}

关于ios - 如何在 SwiftUI 中通过 ViewModel 传播模型更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63839050/

相关文章:

ios - 如何使用 Swift 在 XCode 中颠倒旋转 UILabel?

ios - 稍后以编程方式更改一组 NSLayoutConstraint

ios - AFNetworking "Undefined symbols for architecture i386"错误

mvvm - 在 Windows 10 通用应用程序中将命令绑定(bind)到集线器部分标题单击

c# - 从 WPF 行为向 ViewModel 发送消息

c# - 如何在 WPF 项目中将 rdlc 文件添加到 ReportViewer

swift - SwiftUI 中的滚动和平移冲突

SwiftUI:在我关闭工作表后,navigationBarItems 中的所有按钮不再起作用

swiftui - 我们如何在 SwiftUI 中延迟加载数据到表单/列表?

ios - Chrome IOS HTML5 地理定位权限被拒绝