[英]Should I use `weak self` when making asynchronous network request?
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:
这是我在 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?问题是我应该弱地还是强地捕捉
self
? Why?为什么? I think I can capture it strongly.
我想我可以强烈地捕捉到它。 Because,
fetchProducts
is a function which has closure as a parameter.因为,
fetchProducts
是一个以闭包为参数的函数。 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).因为, ViewModel 对
service
有很强的引用, service
对success
闭包有很强的引用,而success
闭包对self
(也就是 ViewModel)有很强的引用。 It creates retain cycle.它创建了保留循环。 But
deinit
of ViewModel is called anyway, after ViewController
which owns ViewModel is deinitialized.但是,在
deinit
拥有 ViewModel 的ViewController
之后,无论如何都会调用 ViewModel 的 deinit。 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.只要你的viewmodel是一个类,你就必须弱捕获self,否则你会有一个强引用循环。 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.由于
fetchProducts
是异步的,它的成功闭包可能会在您的 viewmodel 已经被释放后执行 - 或者如果闭包没有对它的强引用就会被释放。 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]
.如果您在类中调用
service.fetchProducts
并在异步闭包中访问self
,则确实需要[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]
.如果您要在值类型(
struct
或enum
)中执行此操作,或者如果您没有在闭包内访问self
,则不需要[weak self]
- 在值类型中,您甚至不能执行[weak self]
.
service.fetchProducts(parameters: params, success: { [weak self] response in
self?.isLoading?(false)
/// doing something with response
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.