I'm using UIRefreshControl
on my tableview to update items. And the end, I show a UIAlertController
to inform the user that the update was complete, and how many items were updated. Pretty straightforward, and it works fine for one thing. If I pull to refresh several times in a row, sometimes the refresh control is not dismissed, even after dismissing the alert. I need to swipe up the table to make it go away.
This is the code I use, all UI stuff is nicely done on the main thread:
if(refreshControl.refreshing) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self refreshItems];
dispatch_async(dispatch_get_main_queue(), ^{
[refreshControl endRefreshing];
[self.tableView reload];
[self showUpdateInfo];
});
});
}
Any idea what could cause this?
EDIT: This is how I create the refresh control in code (in viewDidLoad
):
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString: @"Checking for updates…"];
[refreshControl addTarget: self
action: @selector(refreshOutdatedItems)
forControlEvents: UIControlEventValueChanged];
self.refreshControl = refreshControl;
Delaying by an arbitrary time is not a very clean solution. Implementing the delay by counting up a double to 10 million also is a bit of a hack in my opinion.
What I ended up doing instead is similar to this pseudo-Swift:
let alert = UIAlertController(...)
present(alert, animated: true) {
refreshControl.endRefreshing()
}
It delays the call to endRefreshing() until the alert is presented.
My actual code using Swift 3 and PromiseKit looks more like this:
@IBAction func onRefresh() {
Repository.getNewData().then { data in
self.data = data
self.tableView.reloadData()
}.recover { error in
// Return a promise to make sure endRefreshing isn't called until the alert is presented.
return self.presentErrorAlert(message: "Some user-friendly message")
}.always {
self.refreshControl?.endRefreshing()
}
}
private func presentErrorAlert(message: String) -> Promise<Void> {
return Promise<Void> { fulfill, _ in
let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true) {
fulfill()
}
}
}
Those works for me:
refreshControl.endRefreshing()
tableView.setContentOffset(CGPoint.zero, animated: true)
-- show alert than --
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With