Список захвата в закрытии: почему "слабый"?
Я прочитал эту статью о реализации MVVM
, Это демонстрирует приложение master-detail, где есть первый 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]
,
Код доступен для скачивания из статьи, которую я упоминал, или непосредственно из этого репозитория.