UIRefreshControl stops spinning after making appli

2019-06-15 01:35发布

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?

4条回答
forever°为你锁心
2楼-- · 2019-06-15 01:54

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;
    }
}
查看更多
欢心
3楼-- · 2019-06-15 01:54

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;
        });
    }
}
查看更多
女痞
4楼-- · 2019-06-15 01:59

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
        }
    }
}
查看更多
萌系小妹纸
5楼-- · 2019-06-15 02:05

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
    }
}
查看更多
登录 后发表回答