Here is my method to fetch some data from the network:
func fetchProducts(parameters: [String: Any],
success: @escaping ([Product]) -> Void)
As you noticed, it has escaping closure. Here is how I call above method in ViewModel:
service.fetchProducts(parameters: params, success: { response in
self.isLoading?(false)
/// doing something with response
})
The question is should I capture self
weakly or strongly? Why? I think I can capture it strongly. Because, fetchProducts
is a function which has closure as a parameter. But, I might be wrong. But, from other perspective, I think it should be weak. Because, ViewModel has strong reference to service
, service
has strong reference to success
closure which has strong reference to self
(which is ViewModel). It creates retain cycle. But deinit
of ViewModel is called anyway, after ViewController
which owns ViewModel is deinitialized. It means that there was no retain cycle. Why?
As long as your viewmodel is a class, you have to capture self weakly, otherwise you'll have a strong reference cycle. Since fetchProducts
is asynchronous, its success closure might be executed after your viewmodel has already been deallocated - or would have been deallocated if the closure wasn't holding a strong reference to it. The strong reference in the async closure will block the viewmodel from being deallocated.
If you call service.fetchProducts
in a class AND access self
inside the async closure, you do need [weak self]
. If you were to do this in a value type ( struct
or enum
) OR if you didn't access self
inside the closure, you don't need [weak self]
- in a value type, you cannot even do [weak self]
.
service.fetchProducts(parameters: params, success: { [weak self] response in
self?.isLoading?(false)
/// doing something with response
})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.