Шаблон MVVM
Разделяйте ответственность представления, модели представления и модели.
«Шаблон MVVM» — бесплатный урок Swift Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 4 уроков всего.
Что такое MVVM
MVVM — это сокращение от модель–представление–ViewModel. Это архитектурный шаблон, который разделяет приложение на три слоя, каждый из которых отвечает за свою чётко определённую задачу.
- Модель — данные и бизнес-правила
- Представление — то, что видит пользователь
- ViewModel — связующее звено, подготавливающее данные модели для представления
Цель такого подхода — разделение обязанностей: каждый слой изменяется по собственной причине, независимо от остальных.
Слой модели
Модель хранит исходные данные и правила, которые ими управляют. Она ничего не знает об экране и способе отображения данных.
Модели обычно представляют собой простые структуры или объекты предметной области. Их легко тестировать, поскольку у них нет зависимостей от пользовательского интерфейса.
struct User {
let id: UUID
let firstName: String
let lastName: String
let isPremium: Bool
}
struct Order {
let items: [String]
let total: Decimal
}Слой представления
Представление отвечает только за отображение. В SwiftUI это структуры View, а в UIKit — UIViewController и его дочерние представления.
Хорошее представление не содержит бизнес-логики. Оно лишь отображает state и передаёт действия пользователя в ViewModel.
struct ProfileView: View {
@StateObject var viewModel: ProfileViewModel
var body: some View {
VStack {
Text(viewModel.displayName)
if viewModel.showBadge {
Text("Premium")
}
}
}
}Слой ViewModel
ViewModel находится между моделью и представлением. Он получает исходные данные модели и преобразует их в значения, готовые к отображению, которые представление может показывать напрямую.
Он также предоставляет намерения (методы), которые представление вызывает при взаимодействии с пользователем.
final class ProfileViewModel: ObservableObject {
@Published var displayName: String
@Published var showBadge: Bool
init(user: User) {
displayName = user.firstName + " " + user.lastName
showBadge = user.isPremium
}
}Зачем разделять обязанности
Когда форматирование, сетевое взаимодействие и отображение смешаны внутри контроллера представления, этот файл превращается в огромный фрагмент, который невозможно тестировать.
Разделение обязанностей позволяет:
- повторно использовать модель на разных экранах;
- тестировать ViewModel модульными тестами без пользовательского интерфейса;
- сохранить представление небольшим и декларативным.
Что относится к модели
В модель помещают:
- сущности предметной области (
User,Product); - правила бизнес-валидации;
- абстракции хранения данных и сетевого взаимодействия, часто реализованные через службы, которые вызывает ViewModel.
Никогда не помещайте в модель строки интерфейса, цвета или форматирование.
Что относится к ViewModel
ViewModel отвечает за логику представления:
- преобразует даты, валюты и имена в строки для отображения;
- определяет, какие состояния интерфейса видны пользователю: загрузка, ошибка или отсутствие данных;
- координирует вызовы служб и предоставляет результаты.
final class CartViewModel: ObservableObject {
@Published var totalText: String = ""
func update(with order: Order) {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
totalText = formatter.string(from: order.total as NSNumber) ?? "-"
}
}Что относится к представлению
Представление должно только:
- размещать и отображать элементы интерфейса;
- читать опубликованный state из ViewModel;
- передавать нажатия и жесты, вызывая методы ViewModel.
Если внутри представления вы обнаружили if, определяющий бизнес-правила, скорее всего, эту логику следует поместить в ViewModel.
Поток данных в MVVM
Данные движутся в одном направлении, а действия — в обратном:
- Модель -> ViewModel -> Представление — для данных;
- Представление -> ViewModel — для намерений пользователя.
Представление никогда не обращается к модели напрямую. Благодаря этому зависимости направлены внутрь, к предметной области.
MVVM и архитектура с контроллером
В классической архитектуре с контроллером контроллер часто разрастается, поскольку одновременно отвечает за форматирование, сетевое взаимодействие и связывание с представлением.
MVVM выносит эту логику представления в ViewModel, оставляя контроллер, а в SwiftUI — представление, тонким. ViewModel не зависит от фреймворка интерфейса, поэтому его гораздо проще тестировать.
Полный фрагмент
Ниже приведён небольшой, но полный фрагмент MVVM, связывающий все слои.
struct Account { let balance: Decimal }
final class AccountViewModel: ObservableObject {
@Published var balanceText: String
init(account: Account) {
balanceText = "$" + "\(account.balance)"
}
}
struct AccountView: View {
@StateObject var viewModel: AccountViewModel
var body: some View { Text(viewModel.balanceText) }
}Быстрая проверка
Проверьте, насколько хорошо вы понимаете обязанности компонентов MVVM.
Итоги
Вы изучили три слоя MVVM и границы между ними:
- Модель — исходные данные и бизнес-правила, без пользовательского интерфейса;
- ViewModel — логика представления и намерения;
- Представление — только отображение state из ViewModel.
Разделение этих обязанностей делает код тестируемым, пригодным для повторного использования и понятным для анализа. Далее мы свяжем ViewModel с представлением с помощью привязок.
Часто задаваемые вопросы
Урок «Шаблон MVVM» бесплатный?
Да — полный текст урока «Шаблон MVVM» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Swift Academy, подпишись на CoddyKit PRO. Курс Swift Academy содержит 4 уроков всего.
Чему я научусь в уроке «Шаблон MVVM»?
Разделяйте ответственность представления, модели представления и модели. Ты практикуешь Swift Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Swift Academy?
Предыдущий опыт не требуется. Swift Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Шаблон MVVM»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Swift Academy?
Да. Каждый урок Swift Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Шаблон MVVM
- Связывание моделей представления с представлениями
- Шаблон координатора
- Тестирование моделей представления