使用 Combine 实现 Model-View-ViewModel (MVVM) 模式。
CombineViewModel 的主要目标是使 UIKit 和 AppKit 中的视图更新与 SwiftUI 中一样容易。
在 SwiftUI 中,您编写符合 Combine 的 ObservableObject
协议的模型和视图模型类。SwiftUI
@ObservedObject
属性包装器观察每个模型的 objectWillChange
发布者;并且在 SwiftUI 之外使用 objectWillChange
的问题在于,没有内置的方法来实现 (2) —— 被通知对象将要更改与知道对象已经更改并且是时候更新视图是不同的。
考虑以下用于显示用户社交网络配置文件的视图模型的草图
// ProfileViewModel.swift
import CombineViewModel
import UIKit
class ProfileViewModel: ObservableObject {
@Published var profileImage: UIImage?
@Published var topPosts: [Post]
func refresh() {
// Request updated profile info from the server.
}
}
使用 CombineViewModel,您可以使用 observe(on:)
运算符订阅已更改通知
let profile = ProfileViewModel()
profileSubscription = profile.observe(on: DispatchQueue.main).sink { profile in
// Called on the main queue when either (or both) of `profileImage`
// or `topPosts` have changed.
}
profile.refresh()
基于 ObjectDidChangePublisher
构建的是 ViewModelObserver
协议和 @ViewModel
属性包装器。与像上面那样手动管理 ObjectDidChangePublisher
订阅不同,我们可以让它自动管理
// ProfileViewController.swift
import CombineViewModel
import UIKit
// 1️⃣ Conform your view controller to the ViewModelObserver protocol.
class ProfileViewController: UITableViewController, ViewModelObserver {
enum Section: Int {
case topPosts
}
@IBOutlet private var profileImageView: UIImageView!
private var dataSource: UITableViewDiffableDataSource<Section, Post>!
// 2️⃣ Declare your view model using the `@ViewModel` property wrapper.
@ViewModel private var profile: ProfileViewModel
// 3️⃣ Initialize your view model in init().
required init?(profile: ProfileViewModel, coder: NSCoder) {
super.init(coder: coder)
self.profile = profile
}
// 4️⃣ The `updateView()` method is automatically called on the main queue
// when the view model changes. It is always called after `viewDidLoad()`.
func updateView() {
profileImageView.image = profile.profileImage
var snapshot = NSDiffableDataSourceSnapshot<Section, Post>()
snapshot.appendSections([.topPosts])
snapshot.appendItems(profile.topPosts)
dataSource.apply(snapshot)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
profile.refresh()
}
}
在 Example 目录中,您将找到一个完整的 iOS 示例应用程序,演示如何将 CombineViewModel 集成到您的应用程序中。
CombineViewModel 通过 Swift Package Manager 分发。要将其添加到您的 Xcode 项目,请导航到 File > Add Package Dependency…,粘贴存储库 URL,然后按照提示操作。
CombineViewModel 还提供了互补的 Bindings
模块。它提供了两个运算符——<~
,输入绑定运算符,和 ~>
,输出绑定运算符——以及支持它的各种类型和协议。请注意,Bindings 模块提供的“绑定”概念与 SwiftUI 的 Binding
类型 不同。
还提供了特定于平台的绑定帮助程序
在您的项目中有有用的响应式扩展吗?请考虑将其贡献回社区!
有关更多详细信息,请参阅 CONTRIBUTING 文档。谢谢 贡献者!
CombineViewModel 版权所有 © 2019–20 thoughtbot, inc.。它是自由软件,可以根据 LICENSE 文件中规定的条款进行重新分发。
CombineViewModel 由 thoughtbot, inc. 维护和资助。thoughtbot 的名称和徽标是 thoughtbot, inc. 的商标。