了解Swift Closure捕获

时间:2017-06-13 08:35:11

标签: swift closures self-reference

我经历了Swift ClosuresARC in Swift,我感到很困惑。

我有简单的方法来调用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字节
  控制器取消初始化...
  Web服务取消初始化......

我的问题是,即使我在封闭内直接使用self,为什么此实施不会导致参考保留周期
如果我使用unownedweak,那么也会使用相同的行为。

在上述情况下,什么可能导致引用保留周期?(我不想引起,而是想要意识到错误)

2 个答案:

答案 0 :(得分:2)

您的代码中没有问题,因为requestDataFromServer直接调用完成处理程序(无异步)。因此,呼叫期间呼叫者无法释放。

但是当你实现webservice的真实呼叫时,它将是异步的。因此,用户可以在Web服务回答之前切换页面。在这种情况下,您将保留对控制器的强引用,并且它永远不会被释放。你应该在你的闭包中使用[weak self](所以调用self?.useResponseData(responseData)并将self作为可选项。)

如果你确定你的引用不是nil(它不是可选的),则使用

unowned

答案 1 :(得分:0)

好吧,我猜问题就是你在这里做的事实上并不是异步,所以它会一个接一个地执行,这段代码导致内存泄漏:

<div [ngSwitch]="social">
  <div [style.display]="social == 'activity' ? 'block' : 'none'">
    <div #map id="map"></div>
  </div>
  <div *ngSwitchCase="'messages'">
    Some text.....        
  </div>
</div>