Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIRefreshControl stops spinning after making application inactive

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?

like image 553
alexey Avatar asked Feb 13 '14 15:02

alexey


3 Answers

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;
    }
}
like image 116
ogres Avatar answered Nov 15 '22 14:11

ogres


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
    }
}
like image 12
pableiros Avatar answered Nov 15 '22 15:11

pableiros


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
        }
    }
}
like image 6
Ilya Kuznetsov Avatar answered Nov 15 '22 13:11

Ilya Kuznetsov