Управление обновлением Swift 4 не плавное, но всегда скачкообразное

#ios #swift #uitableview #uirefreshcontrol

#iOS #swift #uitableview #uirefreshcontrol

Вопрос:

У меня есть UIViewController, внутри которого есть TableView. Я добавил refreshControl. Но когда я нажимаю, оно всегда скачет несколько раз, что совсем не является плавным и непрерывным.

Я использую Swift 4 и Xcode 10.1.

 class ItemsController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextViewDelegate, ItemCellDelegate {
    ......
    lazy var refreshControl: UIRefreshControl = {
        let refreshControl = UIRefreshControl()
        refreshControl.addTarget(self, action:
            #selector(handleRefresh(_:)),
                                 for: UIControl.Event.valueChanged)
        refreshControl.tintColor = UIColor.lightGray

        return refreshControl
    }()
    ......
    override func viewDidLoad() {
        // Refresh
        self.tableView.refreshControl = self.refreshControl
    }
    ......
    @objc func handleRefresh(_ refreshControl: UIRefreshControl) {
        loadData()
        self.tableView.reloadData()
        refreshControl.endRefreshing()
    }
    ......
}
  

Ответ №1:

Я тоже сталкивался с подобной проблемой. Вы можете использовать этот подход ниже:

  1. Измените свой метод handleRefresh следующим образом:

     @objc func handleRefresh(_ refreshControl: UIRefreshControl) {
       if !tableView.isDragging {
        refresh() // refresh is another method for your reloading jobs
       }
    
    }
      
  2. Добавьте метод обновления.

     func refresh() {
      self.refreshControl.endRefreshing()
      self.tableView.reloadData()
    }
      
  3. Наконец, вам необходимо реализовать scrollViewDidEndDragging. Если вы нажали достаточно низко, refreshControl будет обновляться, поэтому вызовите refresh . В противном случае вы либо недостаточно сильно потянули вниз, либо перетаскивали другую часть таблицы, либо перетаскивали так быстро, что событие refreshControl valueChanged еще не сработало, и оно обновит таблицу там.

     func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
       if refreshControl.isRefreshing == true {
        refresh()
       }
     }
      

Ответ №2:

Является loadData() асинхронным? потому что, если это так, у него должен быть обработчик завершения и

 tableView.reloadData()
refreshControl.endRefreshing()
  

должно быть выполнено (в основном потоке) оттуда. В противном случае происходит то, что пользователь нажимает вниз, и вы мгновенно обновляете TableView и останавливаете управление обновлением, поэтому у вас нет анимации.

Комментарии:

1. Итак, как мне это сделать после завершения loadData ()?

Ответ №3:

попробуйте

 @objc func handleRefresh(_ refreshControl: UIRefreshControl) {
    loadData()
    self.tableView.reloadData()
    DispatchQueue.main.async {
    //DispatchQueue.main.asyncAfter(deadline: .now   0.2) { // or this one with 
    //short delay
       refreshControl.endRefreshing()
    }
}
  

Комментарии:

1. Спасибо! Это делает анимацию более плавной, но все еще есть небольшие скачки.

Ответ №4:

Я просто решил эту проблему, сделав это:

 @objc func handleRefresh(_ refreshControl: UIRefreshControl) {

    refreshControl.endRefreshing()
}

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {

    loadData()
}
  

Довольно просто. Теперь анимация намного лучше.
TableView.reloadData (), который находится внутри loadData(), делает анимацию менее плавной. Поэтому я делаю это после того, как пользователь прекращает перетаскивание.