UIRefreshControl 结束刷新不流畅

UIRefreshControl endRefreshing is not smooth

当我的数据加载完成并且我的 tableView 已重新加载时,我在我的刷新控件上调用 endRefreshing,然后它 'jumps' 从加载状态消失 - 我如何实现一个平滑的动画来滑动完成后刷新控件?

已解决问题 - 我在重新加载数据后向 endRefresh 添加了一个微小的延迟:

[self.tableView reloadData];
[self.refreshControl performSelector:@selector(endRefreshing) withObject:nil afterDelay:0.05];

我正在添加一个新答案,因为唯一的一个解释不是很准确。这对于评论来说可能太多了。

Halpo的解决方案是正确的。但是提到的原因是错误的。

调用-[NSObject (NSDelayedPerforming) performSelector:withObject:afterDelay:]保证在下一次运行循环迭代中执行调用。

所以这是行不通的,因为有一个小的延迟,但你正在将它移到下一个循环。

实际上你 sh/could 将延迟减少到 0.0 并且它仍然有效。此外,更正确的(就使用旨在实现某些目标的对象而言,而不是更好的结果)实现是可能的。

下面是各种代码片段:

// SOLUTION I

[[self tableView] reloadData];
[[self refreshControl] performSelector:@selector(endRefreshing) withObject:nil afterDelay:0.0];

// SOLUTION II (semantically correct)

[[self tableView] reloadData];
[[NSOperationQueue currentQueue] addOperationWithBlock:^{
    [[self refreshControl] endRefreshing];
}];

// SOLUTION III (GCD)

dispatch_async(dispatch_get_main_queue(), ^{
    [[self refreshControl] endRefreshing];
}];

编辑

正如 johann-fradj 所指出的,您也可以使用 GCD。我非常喜欢 GCD,但我认为,解决方案 II 最能描述发生了什么。另外,GCD 不是很 Objective-C-ish,所以我个人宁愿坚持我的解决方案。

原因之一可能是您在调用 endRefresh 后刷新了 table 视图。例如,我的电话过去是这样的:

[self.refreshControl beginRefreshing];
[self.network getThings:^(id things, NSError *error) {
    [self.refreshControl endRefreshing];

    if (error) {
        ...
    } else {
        self.things = things;
        [self.tableView reloadData];
    }
}];

这很糟糕,因为 table 在 endRefresh 动画运行时会自行更新。所以正确完成的代码如下所示:

[self.refreshControl beginRefreshing];
[self.network getThings:^(id things, NSError *error) {
    if (error) {
        [self.refreshControl endRefreshing];
        ...
    } else {
        self.things = things;
        [self.tableView reloadData];
        [self.refreshControl endRefreshing];
    }
}];

尝试在 UIView 动画块中包装对 endRefreshing() 的调用:

我也 运行 关注这个问题。对于 endRefreshing() 文档指出:

UIView.animateWithDuration(0.5) {
    self.refreshControl.endRefreshing()
}

文档指出:

If animations are also enabled, the control is hidden using an animation.

Swift4个解

    tableView.reloadData()
    if refreshControl?.isRefreshing == true {
        DispatchQueue.main.async {
            self.refreshControl?.endRefreshing()
        }
    }

其他解决方案(延迟、使用 CATransaction 等)更复杂,没有任何明显的优势

我的解决方案是 运行 refreshControl?.endRefreshing() 调用 tableView.reloadData():

之前
refreshControl?.endRefreshing()
tableView.reloadData()

当对endRefreshing()的调用在对reloadData()的调用之后时,只要重新加载数据,TableView就会跳转。