SwiftUI-MVVM

yungfan· 2020-05-29

最近看了斯坦福大学 2020 春季的 SwiftUI 课程,总结一下 SwiftUI 是如何支持 MVVM 设计模式的。

介绍

MVVM(Model-View-ViewModel)并非一种框架,而是一种架构模式,一种思想,一种组织和管理代码的方法。它本质上就是 MVC(Model-View- Controller)的一种改进版。

原则

在 MVVM 架构中 View 和 Model 不能直接通信,必须通过 ViewModel。ViewModel 是 MVVM 的核心,它通常要实现一个观察者,当 Model 数据发生变化时 ViewModel 能够监听并通知到对应的 View 做 UI 更新,反之当用户操作 View 时 ViewModel 也能获取到数据的变化并通知 Model 数据做出对应的更新操作。这就是 MVVM 中数据的双向绑定

  1. Model—>View:将数据转化成页面。
  2. View—>Model:将页面转化成数据。

SwiftUI中的MVVM

SwiftUI + Combine 原生就是 MVVM 架构,且能很容易地支持数据的双向绑定。

Model—>View

View—>Model

View<—>Model

结构体与类

class 的最后一条,ViewModel 总是 class 而不是 struct。

案例

  • Model
struct Country: Identifiable {
    let id: UUID = UUID()
    let name: String
}
  • View
struct ContentView: View {

    @ObservedObject var viewModel: ViewModel = ViewModel()

    var body: some View {
        List{
            ForEach(viewModel.countries) { country in
                Text(country.name)
            }
            .onDelete{ index in
                self.viewModel.removeCountry(index.first!)
            }
        }.onAppear {
            self.viewModel.loadCountries()
        }
    }
}
  • ViewModel
class ViewModel: ObservableObject {

    @Published private(set) var countries: [Country] = []

    func loadCountries() {
        self.countries = [Country(name: "中国"), Country(name: "美国"), Country(name: "韩国"), Country(name: "德国"), Country(name: "法国"), Country(name: "英国")]
    }

    func removeCountry(_ index: Int) {
        self.countries.remove(at: index)
    }
}

Model—>View

  1. List(View)显示时onAppear调用,紧接着调用 ViewModel 中的loadCountries()
  2. ViewModel 中的loadCountries()构造/获取数据并转化为 Model。
  3. ViewModel 通过@Published修饰的属性发出数据变化通知。
  4. View 中的@ObservedObject收到通知后驱动 UI 更新。

View—>Model

  1. List(View)侧滑时,进行删除操作,调用 ViewModel 中的removeCountry()
  2. ViewModel 中的removeCountry()操作数据 Model。
  3. ViewModel 通过@Published修饰的属性发出数据变化通知。
  4. View 中的@ObservedObject收到通知后驱动 UI 更新。

我的微信公众号

定期发布 Swift、SwiftUI、Combine、iOS开发等技术文章,也会更新一些自己的学习心得,欢迎大家关注。