【问题标题】:UIRefresh control endRefreshing doesn't workUIRefresh 控件 endRefreshing 不起作用
【发布时间】:2016-10-25 03:29:08
【问题描述】:

当通过向下滑动tableview触发刷新控件时,如果没有互联网连接,则会显示一个警报,并且刷新控件预计会结束刷新,但即使在主线程中添加也不会结束刷新

class JobsForCategoryVC: UIViewController {
    //MARK:-Outlets
    @IBOutlet weak var jobTableView: UITableView!
    @IBOutlet weak var activityIndicator: UIActivityIndicatorView!

    //MARK:-Properties
    var refreshControl:UIRefreshControl!
    var jobCategory:JobCategoryDB!
    var pageNumber:Int = 1
    var downloadMore:Bool = true
    var jobs = [JobModel]()


    //MARK:-LifeCycle
    override func viewDidLoad() {
        super.viewDidLoad()
        setupView()
        freshDownload()
    }

    func setupView(){

        refreshControl = UIRefreshControl()
        refreshControl.attributedTitle = NSAttributedString(string: "Loading fresh Jobs")
        refreshControl.addTarget(self, action: #selector(self.freshDownload), for: .valueChanged)
        jobTableView.addSubview(refreshControl)     

    }

    func freshDownload(){
        pageNumber = 1
        downloadMore = true
        downloadJobsFrom(top: true)
    }


    func downloadJobsFrom(top:Bool){
        if !refreshControl.isRefreshing && top{
            activityIndicator.startAnimating()
        }


        let url = URLStringList.getSearchCategoryJobString(pageNumber: pageNumber, categoryId: jobCategory.id!)

        if let url = URL(string: url){
            Alamofire.request(url, method: .get).responseJSON { (response) in

                if response.result.isSuccess{
                    let json = response.result.value

                    let model = Mapper<JobModel>().mapArray(JSONArray: json as! [[String : Any]])

                    if model?.count == 0{
                        self.downloadMore = false
                    }
                    if let jobs = model{
                        if top{
                              self.jobs = jobs
                        }else{
                            self.jobs += jobs
                        }

                        self.jobTableView.reloadData()
                        self.pageNumber += 1
                    }
                    self.refreshControl.endRefreshing()
                    self.activityIndicator.stopAnimating()

                }else{

                    self.activityIndicator.stopAnimating()
                    DispatchQueue.main.async(execute: {
                        self.refreshControl.endRefreshing()
                        self.jobTableView.reloadData()
                    })

                    if top{
                        showInternetConnectionAlert(viewController: self, activityIndicator: self.activityIndicator, completion: nil)
                    }
                }

            }
        }

    }
}


extension JobsForCategoryVC:UITableViewDataSource{

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if jobs.count > 0 {
            jobTableView.backgroundView = nil
            let cellCount = jobs.count + ((jobs.count-1)/(AdForNumberOfCells-1)) + 1
            return cellCount
        }

        jobTableView.backgroundView =  Bundle.main.loadNibNamed("PullToRefreshView", owner: nil, options: nil)?.first as? PullToRefreshView
        return 0
    }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.row % AdForNumberOfCells  == 0{
            if let cell = tableView.dequeueReusableCell(withIdentifier: "JobsAdTableViewCell", for: indexPath) as? JobsAdTableViewCell{
                cell.controller = self
                return cell
            }

        }else{

            if let cell = tableView.dequeueReusableCell(withIdentifier: "JobsTableViewCell", for: indexPath) as? JobsTableViewCell{
                 let index = NSIndexPath(item: indexPath.row-(indexPath.row/AdForNumberOfCells)-1, section: 0)
                cell.configure(job: jobs[index.row])
                return cell
            }

        }

        return UITableViewCell()
    }

}

extension JobsForCategoryVC:UITableViewDelegate{


    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if let webView = storyboard?.instantiateViewController(withIdentifier: "WKWebVC") as? WKWebVC{
            if indexPath.row % AdForNumberOfCells == 0 {
                return
            }
            let index =  NSIndexPath(item: indexPath.row-(indexPath.row/AdForNumberOfCells)-1, section: 0)

            if let urlString = jobs[index.row].url{
                webView.url = urlString
                webView.titleString = jobs[index.row].title
                present(webView, animated: true, completion: nil)
            }

        }
    }

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        if indexPath.row == self.jobs.count - 1 && downloadMore{
            downloadJobsFrom(top: false)
        }
    }
}

【问题讨论】:

    标签: ios swift uirefreshcontrol


    【解决方案1】:

    这样做的简单方法是

    DispatchQueue.main.async(execute: {
         self.jobTableView.reloadData()
         self.refreshControl.endRefreshing()
         self.activityIndicator.stopAnimating()
         self.refreshControl.setContentOffset(CGPoint.zero, animated: true)
    
    })
    

    【讨论】:

    • 这是一个很好的答案,但方法错误。看看:developer.apple.com/reference/uikit/uirefreshcontrol/…
    • @ak2g 我相信你的意思是说self.jobTableView.setContentOffset(CGPoint.zero, animated: true) 而不是UIRefreshControl 调用setContentOffset 因为UIRefreshControl 没有这样的函数可以调用。
    【解决方案2】:

    UITableView contentOffset 设置为zero

    Swift 3.0

    refreshControl.endRefreshing()
    self.yourTableView.contentOffset = CGPoint.zero
    

    【讨论】:

      【解决方案3】:

      请在主线程中添加所有 UI 程序。

      成功块 => 把你的代码变成:

      if let jobs = model{
           if top{
              self.jobs = jobs
           }else{
              self.jobs += jobs
           }
           self.pageNumber += 1                       
      }
      
      DispatchQueue.main.async(execute: {
           self.refreshControl.endRefreshing()
           self.activityIndicator.stopAnimating()
           self.jobTableView.reloadData()
      })
      

      还有失败块:

      DispatchQueue.main.async(execute: {
           self.refreshControl.endRefreshing()
           self.activityIndicator.stopAnimating()
           self.jobTableView.reloadData()
      })
      

      无论成功还是失败,你所有的UI Progress都必须包含在主线程中。我想你忘记在Success Block中包含主线程内的UI Changes了。或者你可以这样做,

      Alamofire.request(url, method: .get).responseJSON { (response) in
           if response.result.isSuccess{
                ...
           }else{
                ...
           }
           DispatchQueue.main.async(execute: {
                self.refreshControl.endRefreshing()
                self.activityIndicator.stopAnimating()
                self.jobTableView.reloadData()
           })
      }
      

      看看:

      RefreshControlDemo[Swift 3 Xcode 8]

      【讨论】:

      • 如果我按照你说的做,在你的 setupView() jobTableView.addSubview(refreshControl) 中删除以下代码,那么 UiRefresh 控件将不在视图层次结构中。您是在要求我删除有问题的功能,而不是解决问题。
      • @SamipShah,对不起,我以为你在使用 UITableViewController。我上传了示例。你可能想检查一下。不需要将 refreshControl 的 contentOffset 设置为零。请使用 Legacy Swift 版本构建此项目时选择“是”。
      • 完成编辑。如果您看到这个演示项目,您可能会理解不需要设置 Offset = 零来隐藏 UIRefreshControl,因为它会在 endRefreshing 时自动完成。您可能需要再次检查您的代码。
      • 我已经看到了错误的原因,请看一下我编辑的答案。您必须在重新加载表之前调用 endRefreshing。如果没有,在重新加载表后,它可能会给 UIRefreshControl 带来一些错误。希望这有帮助。参考这个:stackoverflow.com/questions/27280544/…
      【解决方案4】:

      我发现同样的问题

      如果另一个使用 self.refresh.endRefreshing() 不起作用

      我介绍这段代码 -> UIRefreshControl().endRefreshing() 替换状态为self.refresh.endRefreshing()

       DispatchQueue.main.async {
      
             UIRefreshControl().endRefreshing()
             self.yourTableView.contentOffset = CGPoint.zero
      
       }
      

      谢谢

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-18
        • 2018-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-16
        相关资源
        最近更新 更多