Ответ
MVVM (Model-View-ViewModel) — это архитектурный паттерн, который разделяет ответственность, упрощает тестирование и уменьшает связность кода.
Структура компонентов:
- Model: Представляет данные и бизнес-логику (например, структуры
User,Post). - View: Отвечает за отображение UI и пользовательские взаимодействия (
UIViewController,UIView,SwiftUI View). View содержит ссылку на ViewModel, но не наоборот. - ViewModel: Промежуточный слой, который преобразует данные Model в удобный для View формат. Он не должен импортировать
UIKit/SwiftUI.
Пример реализации с биндингом через замыкания:
// Model
struct User {
let name: String
let email: String
}
// ViewModel
class UserViewModel {
private let user: User
// Published свойства для биндинга
var userName: String { user.name }
var userEmail: String { user.email }
// Замыкание для обновления View
var onUpdate: (() -> Void)?
init(user: User) {
self.user = user
}
func fetchUserData() {
// Сетевой запрос или работа с БД
// После получения данных вызываем onUpdate?()
}
}
// View (UIViewController)
class UserViewController: UIViewController {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var emailLabel: UILabel!
var viewModel: UserViewModel! {
didSet {
viewModel.onUpdate = { [weak self] in
self?.updateUI()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
viewModel.fetchUserData()
}
private func updateUI() {
nameLabel.text = viewModel.userName
emailLabel.text = viewModel.userEmail
}
}
Преимущества:
- Тестируемость: ViewModel легко тестируется юнит-тестами без UI.
- Разделение ответственности: View занимается только отрисовкой, ViewModel — подготовкой данных.
- Гибкость: Для биндинга можно использовать
Combine,RxSwiftили простые замыкания.
Важно: ViewModel не должна хранить сильные ссылки на View, чтобы избежать циклов удержания.