【发布时间】:2015-04-18 01:32:35
【问题描述】:
当我的数据已完成加载并且我的 tableView 已重新加载时,我在刷新控件上调用 endRefreshing,然后它从其加载状态“跳跃”并消失 - 我如何实现一个平滑的动画,使刷新控件滑开时完成了吗?
【问题讨论】:
标签: ios user-interface animation tableview
当我的数据已完成加载并且我的 tableView 已重新加载时,我在刷新控件上调用 endRefreshing,然后它从其加载状态“跳跃”并消失 - 我如何实现一个平滑的动画,使刷新控件滑开时完成了吗?
【问题讨论】:
标签: ios user-interface animation tableview
我正在添加一个新答案,因为唯一的答案在解释上不是很精确。而这对于 cmets 来说可能太过分了。
Halpo 的解决方案是正确的。但是上面的理由是错误的。
调用-[NSObject (NSDelayedPerforming) performSelector:withObject:afterDelay:]保证调用在下一次runloop迭代中执行。
所以这不起作用,因为有一个小的延迟,但你正在将它移动到下一个循环。
实际上,您可以/可以将延迟减少到0.0,它仍然可以工作。此外,更正确的(就使用旨在实现某事的对象而言,而不是更好的结果)实现是可能的。
这里是各种代码sn-ps:
// 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,所以我个人宁愿坚持我的解决方案。
【讨论】:
[refreshControl endRefreshing] 重新加载 tableview 时提交 CATransaction 会产生非常流畅的动画。我承认这感觉像是一种 hack,因为据我所知 [tableView reloadData] 是不可动画的,但这是在我的特定情况下唯一有效的解决方案。
修复了问题 - 我在重新加载数据后对 endRefresh 添加了一个微小的延迟:
[self.tableView reloadData];
[self.refreshControl performSelector:@selector(endRefreshing) withObject:nil afterDelay:0.05];
【讨论】:
self.refreshControl.perform(#selector(UIRefreshControl.endRefreshing), with: nil, afterDelay: 0)
Swift 4 解决方案
tableView.reloadData()
if refreshControl?.isRefreshing == true {
DispatchQueue.main.async {
self.refreshControl?.endRefreshing()
}
}
其他解决方案(延迟,使用 CATransaction,...)更复杂,没有任何明显的优势
【讨论】:
尝试将调用 endRefreshing() 包装在 UIView 动画块中:
我也遇到过这个问题。对于endRefreshing() 文档说明:
UIView.animateWithDuration(0.5) {
self.refreshControl.endRefreshing()
}
文档说明:
如果还启用了动画,则使用动画隐藏控件。
【讨论】:
其中一个原因可能是您在调用 endRefresh 后刷新了表格视图。例如,我的电话过去看起来像这样:
[self.refreshControl beginRefreshing];
[self.network getThings:^(id things, NSError *error) {
[self.refreshControl endRefreshing];
if (error) {
...
} else {
self.things = things;
[self.tableView reloadData];
}
}];
这很糟糕,因为在 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];
}
}];
【讨论】:
endRefreshing 。您将使您的代码“更小”并且更具可读性。此外,如果您只对开发过程中的错误原因感兴趣(您不应该这样做),您可以简单地反转 if 并使用更少的代码。
我的解决方案是在调用tableView.reloadData()之前运行refreshControl?.endRefreshing():
refreshControl?.endRefreshing()
tableView.reloadData()
当调用endRefreshing() 是在调用reloadData() 之后,每当重新加载数据时,TableView 就会跳转。
【讨论】: