【问题标题】:Retain cycle in Async calls while updating UI在更新 UI 时保持异步调用中的循环
【发布时间】:2018-03-12 18:24:05
【问题描述】:

以下是我使用的代码。使用此代码不会调用 deinit,但是如果我从代码中注释掉这一行 weakSelf?.tableView.reloadData() 会调用 deinit。我做错了吗?

ZLNetworkHelper.sharedManager.getUserSavedAddress { (response) in
        print("getUserSavedAddressFinished")
        ZLProgressIndicator.stopAnimation()
        if response.isSuccess && response.value != nil {

            weak var weakSelf = self
            guard weakSelf != nil else {
                return
            }

            weakSelf!.address = response.value!.sorted(by: {$0.isDefault && !$1.isDefault})
            weakSelf!.isExistingAddressSectionExpanded = false

            if weakSelf!.address.count == 0 {
                weakSelf!.title  = LocalizationUtility.RCLocalizedString("ADD_ADDRESS")
            }

            DispatchQueue.main.async {
                weakSelf!.tableView.reloadData()
            }
            if completion != nil {
                completion!(true)
            }
        }
        else {

            let message = response.error?.localizedDescription
            ZLCustomAlertVC.presentAlertInVC(self, withErrorMessage:message)
        }
    }

【问题讨论】:

  • 我知道你确实使用了guard,但是 FWIW 因为它是一个异步调用,你的强制解包仍然可能崩溃!请参阅this 评论和完整答案
  • @Honey 感谢您提供此信息,真的很有帮助。

标签: ios swift retain-cycle


【解决方案1】:

你想在闭包中弱弱地捕获自我:

getUserSavedAddress { [weak self] (response) in

当您稍后捕获它时,您仍然会在闭包中获取对 self 的引用。

尝试这样的实现:

ZLNetworkHelper.sharedManager.getUserSavedAddress { [weak self] (response) in
    DispatchQueue.main.async {
        print("getUserSavedAddressFinished")
        ZLProgressIndicator.stopAnimation()
        if response.isSuccess && response.value != nil {


           self?.address = response.value!.sorted(by: {$0.isDefault && !$1.isDefault})
            self?.isExistingAddressSectionExpanded = false

            if self?.address.count == 0 {
                self?.title  = LocalizationUtility.RCLocalizedString("ADD_ADDRESS")
            }

                self?.tableView.reloadData()
            if completion != nil {
                completion!(true)
            }
        }
        else {

            let message = response.error?.localizedDescription
            ZLCustomAlertVC.presentAlertInVC(self, withErrorMessage:message)
        }
    }   
}

(我只在 SO 上更新了这个,所以你可能需要根据需要解包等)

【讨论】:

  • 我做了这个改变然后也没有调用 Deinit
  • 我已经完全使用了你在答案中写的内容,没有调用 deinit 。如果我删除 tableViewReloadData() deinit 会被调用。
  • Inside tableView CellforRowAtIndexPath 方法我正在设置这样的委托 cell.delegate = self,如果我删除此行,则调用 Deinit,我应该如何处理?跨度>
  • @AjayKumar 情况不同,单元格的委托应该定义为弱变量,例如:'weak var delegate: DelgateType?'
  • 我的错,问题是这样的,委托 var 在单元格中并不弱,现在一切正常,如果我使用我发布的原始代码也使用弱自我的方式工作正常。
【解决方案2】:

您可以使用 Fred Faust 提供的代码,但在显示警报的 else 部分也可以使用 weakself。

【讨论】:

    猜你喜欢
    • 2019-07-02
    • 2020-06-27
    • 2010-09-14
    • 1970-01-01
    • 2019-07-07
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 2018-01-23
    相关资源
    最近更新 更多