#ios #mvvm #model #viewmodel #encapsulation
#iOS #mvvm #Модель #viewmodel #инкапсуляция
Вопрос:
Я хотел бы применить MVVM
шаблон в моем следующем проекте iOS, и я прочитал несколько сообщений и блогов об этом. Но примеры, которые они показывают, очень простые, без бизнес-логики, только объекты модели данных View
и Model
обновления. Мне не ясно, кто на самом деле отвечает за управление бизнес-логикой и операциями: должно ли это быть ViewModel
или Model
?
Например, предположим, что одна из моих функций должна:
- Запрашивать некоторые данные для веб-службы
- Проанализируйте такие данные и сопоставьте их с объектами моей модели данных
- Выполните некоторые проверки и операции над такими объектами и обновите оба
View
иModel
с результатами - Обработайте таймер, который запускает еще несколько обновлений и операций
Как я должен распределить эти обязанности для реализации MVVM
?
Ответ №1:
Из потока данных в MVVM мы можем видеть обязанности ViewModel:
Data Flow in MVVM
1. UI calls method from ViewModel (Presenter).
2. ViewModel executes Use Case.
3. Use Case combines data from User and Repositories.
4. Each Repository returns data from a Remote Data (Network), Persistent DB Storage Source or In-memory Data (Remote or Cached).
5. Information flows back to the UI where we display the list of items.
Более подробное описание MVVM можно найти здесь: https://tech.olx.com/clean-architecture-and-mvvm-on-ios-c9d167d9f5b3
Ответ №2:
Допустим, есть веб-сервис для получения комментариев
Вы можете создать CommentService, который отвечает за загрузку данных, синтаксический анализ и инициализацию / обновление модели. Потому что нам нужно получить комментарии, поэтому есть метод
func getComments(_ completion: () -> [Comment])
CommentService.getComments
вызывается ViewModel в его методе загрузки.
class ViewModel {
private let commentService: CommentService
private var comments: [Comment]
...
func load() {
commentService.getComments() { [weak self] comments in
self?.comments = comments
//notify somehow the view..for example by using delegate
}
}
}
Например, мы хотим понизить / повысить голоса в комментариях, чтобы мы могли это реализовать
struct CommentService {
...
func upvote(comment: Comment, completion: (Void) -> (Comment)) {
if comment.upvoted {
//throw error
}
//update via web service and update Comment's model by the response or just increment the comment.upvotes
//call completion with updated comment
}
}
struct ViewModel {
func upvoteComment(at index:Int, completion: (() -> ())?) {
commentService.upvote(comments[index]) { updatedComment in
//do some more stuff with viewModel
completion?() //in the completion is implemented updating of ui
}
}
}
Блоки завершения могут обеспечить способ обновления пользовательского интерфейса без необходимости какого-либо делегирования или уведомлений
Когда таймер запускает метод, завершение операции может вызвать метод делегирования для обновления представления. Другой вариант — использовать структуру привязки (например, Bond), тогда view может наблюдать свойства ViewModel, и делегирование не требуется.
https://github.com/thefuntasty/MVVMTestProject/tree/master/testMVVM Может быть, этот проект поможет вам понять.