I use UIRefreshControl in a UITableView:
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(refresh)
forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
With refresh handler:
-(void)refresh {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// (...some long running operation...)
dispatch_async(dispatch_get_main_queue(), ^{
[self.refreshControl endRefreshing];
});
});
}
During the long running operation I make the application inactive pressing Home button. After that I make the application active again. The spinner freezes (stops spinning) and there is no way to return it to the initial state.
How to fix it?
I think it is a bit delayed answer but , today I saw similar issue on ios 7 , ios 6 continued spinning ,
here is a little workaround for this
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if(self.refreshControl.isRefreshing) {
CGPoint offset = self.tableView.contentOffset;
[self.refreshControl endRefreshing];
[self.refreshControl beginRefreshing];
self.tableView.contentOffset = offset;
}
}
it will stop and start again spinning , but it only happened on ios7 with me , so maybe you should check not to do it on ios6
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if(self.refreshControl.isRefreshing && [[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
CGPoint offset = self.tableView.contentOffset;
[self.refreshControl endRefreshing];
[self.refreshControl beginRefreshing];
self.tableView.contentOffset = offset;
}
}
This is what worked for me
Swift 3 and Swift 4:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if self.refreshControl?.isRefreshing == true {
let offset = self.tableView.contentOffset
self.refreshControl?.endRefreshing()
self.refreshControl?.beginRefreshing()
self.tableView.contentOffset = offset
}
}
Swift 2.3:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if self.refreshControl?.refreshing == true {
let offset = self.tableView.contentOffset
self.refreshControl?.endRefreshing()
self.refreshControl?.beginRefreshing()
self.tableView.contentOffset = offset
}
}
In iOS 11 this approach works much better than the others
class AMRefreshControl: UIRefreshControl {
override func didMoveToWindow() {
super.didMoveToWindow()
if window != nil && isRefreshing, let scrollView = superview as? UIScrollView {
let offset = scrollView.contentOffset
UIView.performWithoutAnimation {
endRefreshing()
}
beginRefreshing()
scrollView.contentOffset = offset
}
}
}
This still is an issue in iOS11. The solution needs to be modified a bit though, otherwise the refresh control will spin too fast
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if(self.refreshControl.isRefreshing) {
CGPoint offset = self.tableView.contentOffset;
[self.refreshControl endRefreshing];
// Delay the restart
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.refreshControl beginRefreshing];
self.tableView.contentOffset = offset;
});
}
}