Ios 发出异步网络请求时是否应使用'weak self'?

Ios 发出异步网络请求时是否应使用'weak self'?,ios,swift,memory-management,automatic-ref-counting,retain-cycle,Ios,Swift,Memory Management,Automatic Ref Counting,Retain Cycle,以下是我从网络中获取一些数据的方法: func fetchProducts(parameters: [String: Any], success: @escaping ([Product]) -> Void) 正如您所注意到的,它有逃逸关闭。以下是我在ViewModel中调用上述方法的方式: service.fetchProducts(parameters: params, success: { response in self.isLo

以下是我从网络中获取一些数据的方法:

func fetchProducts(parameters: [String: Any],
                success: @escaping ([Product]) -> Void) 
正如您所注意到的,它有逃逸关闭。以下是我在ViewModel中调用上述方法的方式:

service.fetchProducts(parameters: params, success: { response in
        self.isLoading?(false)
        /// doing something with response
}) 

问题是我应该弱地还是强地捕捉自己?为什么?我想我能牢牢抓住它。因为,
fetchProducts
是一个以闭包作为参数的函数。但是,我可能错了。但是,从另一个角度来看,我认为它应该是脆弱的。因为,ViewModel强烈引用了
服务
服务
强烈引用了
成功
关闭,它强烈引用了
自我
(即ViewModel)。它创造了一个循环。但是,在拥有ViewModel的
ViewController
被取消初始化之后,ViewModel的
deinit
仍然被调用。这意味着没有保留周期。为什么?

只要您的viewmodel是一个类,您就必须弱地捕获self,否则您将有一个强引用循环。由于
fetchProducts
是异步的,因此它的成功闭包可能会在您的viewmodel被解除分配后执行,或者如果闭包没有包含对它的强引用,它可能会被解除分配。异步闭包中的强引用将阻止释放viewmodel

如果在类中调用
service.fetchProducts
,并在异步闭包中访问
self
,则确实需要
[弱self]
。如果要在值类型(
struct
enum
)中执行此操作,或者如果没有在闭包中访问
self
,则不需要在值类型中执行
[弱自我]
,甚至不能执行
[弱自我]

service.fetchProducts(parameters: params, success: { [weak self] response in
        self?.isLoading?(false)
        /// doing something with response
}) 

是,ViewModel是引用类型。但是,您如何解释即使存在强self,也会调用ViewModel的Denit?@neo是否会创建强引用循环,取决于何时执行闭包以及何时解除对ViewModel的所有其他引用。仅当最后一个引用位于关闭内时,强引用循环才会关闭。因此,例如,如果您的网络请求花了10秒才返回结果,但您的用户在5秒后已经离开了存储视图模型的视图,那么由于使用了强self,将有一个强引用周期。您可以通过捕获self来防止这种情况。好的,但是假设我的网络请求需要10秒。用户从该屏幕中导航出来。当然,我的ViewModel不能被删除。但在执行
success
closure之后,它将被释放。我哪里错了?@DávidPásztor举个例子,如果你的网络请求花了10秒。。这不是完全正确的,我正好遇到了这种情况,当网络结束并得到响应时,所有内容都成功解除分配。@neo,不,即使在请求返回后也不会解除分配。这就是你错的地方。创建内存泄漏是因为viewmodel应该在释放该闭包之外的所有引用时立即释放。但是,包含对viewmodel的引用的闭包会创建一个不会被释放的僵尸对象。