假设有一个获取 cmets 的 Web 服务
您可以创建 CommentService 负责下载数据、解析和初始化/更新模型。因为我们需要获取cmets,所以有一个方法
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
}
}
}
例如,我们想要对 cmets 投反对票/赞成票,所以我们可以实现它
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
}
}
}
完成块可以提供更新 ui 的方式,而无需任何委托或通知
当定时器触发方法时,操作结束可以调用委托方法更新视图。另一种选择是使用绑定框架(例如Bond),然后视图可以观察ViewModel 属性并且不需要委托。
https://github.com/thefuntasty/MVVMTestProject/tree/master/testMVVM
也许这个项目可以帮助你理解。