我有调用web服务和使用响应数据的简单场景。
以下是我的基本实现:
class WebServices: NSObject {
func requestDataFromServer(completion: @escaping (_ data: Data?) -> Void) {
//web service call here
completion(Data())
}
deinit {
print("WebServices deinitializer...")
}
}
class Controller: NSObject {
private let webService = WebServices()
private func useResponseData(_ data: Data) {
print("Response Data: \(data)")
}
func fetchData() {
webService.requestDataFromServer { (data) in
if let responseData = data {
self.useResponseData(responseData)//direct use of self
}
}
}
deinit {
print("Controller deinitializer...")
}
}
var controller: Controller? = Controller()
controller!.fetchData()
controller = nil控制台输出是:
响应数据:0字节 控制器去初始化器。 WebServices去初始化器..。
我的问题是,我甚至在闭包中直接使用self,为什么这个实现没有导致引用保留周期
如果我使用unowned或weak,那么也会有相同的行为。
在上述情况下,什么能导致引用保持循环?(我不想引起,而是要注意错误)
发布于 2017-06-13 09:25:11
代码中没有问题,因为requestDataFromServer直接调用完成处理程序(没有异步)。所以打电话的人不可能在你打电话的时候被释放。
但是,当您实现when服务的真正调用时,它将是异步的。这样用户就可以在can服务回答之前切换页面。在这种情况下,您将保留对控制器的强烈引用,并且它将永远不会被释放。您应该在闭包中使用[weak self](因此调用self?.useResponseData(responseData)并将self作为可选的)。
如果您确信引用不会为零(它不是可选的),则使用unowned。
发布于 2017-06-13 09:10:56
好的,我想问题是您在这里所做的并不是真正的异步,所以它一个接一个地执行,这段代码会导致内存泄漏:
import Foundation
class WebServices {
func requestDataFromServer(completion: @escaping (_ data: Data?) -> Void) {
//web service call here
print("called")
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1, execute: {
print("called async")
completion(Data())
})
}
deinit {
print("WebServices deinitializer...")
}
}
class Controller: UIViewController {
private let webService = WebServices()
private func useResponseData(_ data: Data) {
print("Response Data: \(data)")
}
func fetchData() {
webService.requestDataFromServer { (data) in
print("called")
if let responseData = data {
self.useResponseData(responseData)//direct use of self
}
}
self.dismiss(animated: true, completion: nil)
}
deinit {
print("Controller deinitializer...")
}
}
var controller: Controller? = Controller()
controller!.fetchData()https://stackoverflow.com/questions/44516257
复制相似问题