#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:
Я тоже сталкивался с подобной проблемой. Вы можете использовать этот подход ниже:
-
Измените свой метод handleRefresh следующим образом:
@objc func handleRefresh(_ refreshControl: UIRefreshControl) { if !tableView.isDragging { refresh() // refresh is another method for your reloading jobs } }
-
Добавьте метод обновления.
func refresh() { self.refreshControl.endRefreshing() self.tableView.reloadData() }
-
Наконец, вам необходимо реализовать 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(), делает анимацию менее плавной. Поэтому я делаю это после того, как пользователь прекращает перетаскивание.