【问题标题】:Why sometimes completion handler not called?为什么有时不调用完成处理程序?
【发布时间】:2019-11-01 01:18:15
【问题描述】:

问题是有时(不总是)我的完成处理程序变为 nil。

我已经尝试过[弱自我],但它不起作用。

func setup() {
 _collectionView.refreshControl?.addTarget(self, action: #selector(refresh(sender:)), for: .valueChanged)
}
 @objc private func refresh(sender: UIRefreshControl) {
       print("request1")
       request(refresh: true, completion: { () -> Void in
           // When completion become nil, this is not called.
           (sender as UIRefreshControl).endRefreshing()
           print("completion1")
       })
   }


   fileprivate func request(refresh: Bool, completion: (() -> Void)? = nil) {

       guard !isFetchInProgress else {
           return
       }
       isFetchInProgress = true

       APIRequest.request(request: request).success { [weak self] result in
           Log.debugLog(“success!:%@“, result)
               if let _self = self {
                   if RequestResponseManager.sharedInstance.handleResponse(response: result) {
                        if let _data = result.data {
                         print(_data)
                   }
               }
           }.failure { error, _ in
               Log.debugLog(“%@“, error.debugDescription)
               completion?()
               isFetchInProgress = false
           }.then { _,_  in
               Log.debugLog(“then!“)    

               // SOMETIMES (not always) completion?() become nil
               completion?()
               isFetchInProgress =false
           }
   }
    public func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

        var target: UICollectionReusableView? = nil
  if kind == UICollectionView.elementKindSectionFooter {
            target = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: footerId, for: indexPath)

            if isNeedRequest {
                print("request2")
                self.request(refresh: false)
            }
        }

        return target!
    }

1、当上下滚动速度正常时,log显示如下,没关系。

request1
completion1
request2

2、但是当向下和向上滚动速度更快时,日志显示如下,并且从未调用completion1并停止refreshControl。

request1
request2

我想知道如何正确处理它? 谢谢。

【问题讨论】:

  • 你确定 APIRequest 总是完成吗?例如:当isFetchInProgress 为真时,API 请求甚至永远不会启动,并且永远不会调用完成处理程序。
  • 看起来在这种情况下completion 被强烈引用,并且在任何情况下都不能设置为nil,甚至没有明确设置。唯一的方法是nil,因为它已经被注入为nil。因此,某处某处正在调用request(refresh: flag, completion: nil)
  • @wvteijlingen 感谢您的评论。 debugLog 总是显示。失败或.then
  • @MaticOblak 感谢您的回复。实际上 request(refresh: false) 是在 collectionView 滚动到最后时从其他方法调用的。如何避免@objc private func refresh(sender: UIRefreshControl) completion 被注入为零?
  • @Alea 能否请您也添加该代码?

标签: ios swift


【解决方案1】:

完成处理程序不会“变成” nil。如果在调用方法时没有提供完成处理程序,则默认为nil

你的方法被声明了

fileprivate func request(refresh: Bool, completion: (() -> Void)? = nil)

这意味着实际上有两种调用此方法的方法。您可以使用完成处理程序调用它:

request(refresh: true) {
    // this is the completion handler
}

request(refresh: false) {
    // this is the completion handler
}

但您也可以将其称为 完成处理程序:

request(refresh: true)

request(refresh: false)

在这种情况下,在您的 request 方法中,completion 将是 nil。因此,如果您不希望 completion 成为 nil,请不要这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-08
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    相关资源
    最近更新 更多