Скажем, есть веб-сервис для получения комментариев
Вы можете создать 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
}
}
}
Например, мы хотим downvote/upvote комментарии, так что мы можем реализовать это
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), тогда представление может наблюдать свойства ViewModel, и делегат не нужен.
https://github.com/thefuntasty/MVVMTestProject/tree/master/testMVVM Возможно, этот проект поможет вам разобраться.