我阅读了article的有关实现MVVM
的内容。它展示了一个主从应用程序,其中第一个viewController
处理表格视图,并且还包含一个viewModel
。这样的viewModel
调用了模拟服务,以使某些图片显示在表视图中。 viewController
和viewModel
通过闭包进行绑定。
viewController
像这样:
lazy var viewModel: PhotoListViewModel = {
return PhotoListViewModel()
}()
func initVM() {
// Some code here
viewModel.reloadTableViewClosure = { [weak self] () in
DispatchQueue.main.async {
self?.tableView.reloadData()
}
}
viewModel.initFetch()
}
还有viewModel
:
private var cellViewModels: [PhotoListCellViewModel] = [PhotoListCellViewModel]() {
didSet {
self.reloadTableViewClosure?()
}
}
var reloadTableViewClosure: (()->())?
init( apiService: APIServiceProtocol = APIService()) {
self.apiService = apiService
}
func initFetch() {
self.isLoading = true
apiService.fetchPopularPhoto { [weak self] (success, photos, error) in
self?.isLoading = false
if let error = error {
self?.alertMessage = error.rawValue
} else {
self?.processFetchedPhoto(photos: photos)
}
}
}
private func processFetchedPhoto( photos: [Photo] ) {
self.photos = photos // Cache
var vms = [PhotoListCellViewModel]()
for photo in photos {
vms.append( createCellViewModel(photo: photo) )
}
self.cellViewModels = vms
}
我需要了解此代码示例中的捕获列表:
1。。看到viewController
:
看来您实际上可以在那里拥有一个强大的参考周期,对吗? viewController
包含对viewModel
的引用,该引用包含一个闭包,该闭包将self
(viewVController
)捕获在其主体内。那是对的吗?那么,为什么reloadTableViewClosure
用[weak self]
方法设置initVM()
?
这个viewModel
应该是根源,因此它在整个应用程序生命中都还活着,所以实际上viewModel
的寿命可能较短,对吧?那不意味着应该使用unowned
来代替?
要考虑的另一件事是,也许viewModel
可以调用另一个对象来执行异步任务,然后viewModel
将被此类对象保留,直到异步任务返回,对吗?然后,这种情况可能会更改我之前提到的viewController
中的捕获列表?
1。。看到viewModel
:
在其initFetch()
方法中,将调用apiService
对象。在这种情况下,它看起来要执行同步任务,但是如果它是真正的REST服务调用,它将是异步的。无论如何,apiService
对象将保留viewModel
,直到其任务完成,对吗?因此,同样,那里可能会有一个强大的参考保留周期->传递给apiService
的闭包为@escaping
,并且self
被捕获在主体中。正确吗?
此处捕获列表也为[weak self]
。当weak
的寿命可以缩短时,您设置self
吧?但是viewModel
的生命是否可以短于apiService
回调的生命? apiService
是否保留viewModel
。另一方面,由于viewModel
是由根viewController
持有的,因此整个应用程序生命也不会一整天吗?
我需要澄清一些信息,以了解那里潜在的强参考周期以及为什么所有这些捕获列表都考虑使用[weak self]
。
可以从article I mentioned或直接从repo
下载代码。