iOS MVVM 不用RAC 如何实现双向绑定
在iOS开发中,MVVM(Model-View-ViewModel)是一种常用的架构模式,它有助于分离视图逻辑与业务逻辑,提高代码的可维护性和可测试性。本文将探讨如何在MVVM架构中实现双向绑定,而不依赖ReactiveCocoa(RAC)。我们将通过一个具体的例子来说明如何进行数据的双向绑定,以便用户在界面中修改数据后,这些修改能够即时反映到模型中。
问题描述
假设我们有一个简单的用户信息界面,用户可以在界面上输入他们的姓名和年龄信息。我们希望一旦用户在界面上输入信息,相关的模型数据也能够立即更新。而反过来,当模型数据发生变化时,界面也应该相应更新。
解决方案
我们将创建一个UserViewModel
类,该类将作为MVC架构中的ViewModel,它将管理用户输入和用户数据模型之间的绑定。下面是实现的核心类结构:
类图
classDiagram
class User {
+String name
+Integer age
}
class UserViewModel {
+User user
+String name
+Integer age
+updateUserData()
}
实现代码
首先,我们定义一个User
模型类,用于表示用户的数据:
class User {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
接下来,我们创建一个UserViewModel
类来处理数据与视图之间的交互:
class UserViewModel {
private var user: User {
didSet {
// Notify the view to update after user data changed
self.onUserUpdate?()
}
}
var name: String {
get {
return user.name
}
set {
user.name = newValue
}
}
var age: Int {
get {
return user.age
}
set {
user.age = newValue
}
}
var onUserUpdate: (() -> Void)?
init(user: User) {
self.user = user
}
func updateUserData() {
// Custom logic if needed to process data when required
// For now, simply notify the UI
onUserUpdate?()
}
}
视图部分
在UIViewController中,我们将实现输入框和标签,并通过ViewModel与视图建立绑定。
class UserViewController: UIViewController {
private var viewModel: UserViewModel!
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var ageTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Initialize ViewModel with User
let user = User(name: "John", age: 25)
viewModel = UserViewModel(user: user)
// Update UI with existing user data
nameTextField.text = viewModel.name
ageTextField.text = "\(viewModel.age)"
// Binding text field changes to ViewModel
nameTextField.addTarget(self, action: #selector(nameDidChange), for: .editingChanged)
ageTextField.addTarget(self, action: #selector(ageDidChange), for: .editingChanged)
// Notify when user data is updated
viewModel.onUserUpdate = { [weak self] in
self?.nameTextField.text = self?.viewModel.name
self?.ageTextField.text = "\(self?.viewModel.age ?? 0)"
}
}
@objc private func nameDidChange() {
viewModel.name = nameTextField.text ?? ""
}
@objc private func ageDidChange() {
if let ageText = ageTextField.text, let age = Int(ageText) {
viewModel.age = age
}
}
}
序列图
sequenceDiagram
participant User as User
participant VM as UserViewModel
participant View as UserViewController
View->>VM: nameTextField text change
VM->>User: update name
User-->>VM: name updated
VM->>View: update UI
View-->>User: Show updated name
结论
通过上述实现,我们成功构建了一个简单的双向绑定机制,能够在用户输入数据时自动更新模型,同时在模型更改时更新视图。尽管没有使用 ReactiveCocoa,使用关闭和 KVO(键值观察)等方式也可轻松实现数据绑定。这样的设计使得代码结构清晰,逻辑分离,提升了可维护性。希望本文的示例能对您的MVVM实践有所帮助。