当我的数据加载完成并且表格视图已经重新加载时,我会在刷新控件上调用endRefreshing方法,它会从其加载状态“跳出”并消失 - 我该如何实现一个平滑的动画,在完成时将刷新控件滑开?
鉴于唯一的答案解释不太精确,我会添加一个新的答案。而且这可能对评论来说太多了。
Halpo 的解决方案是正确的。但所提到的原因是错误的。
调用 -[NSObject (NSDelayedPerforming) performSelector:withObject:afterDelay:]
保证在下一次运行循环迭代中执行该调用。
所以这不起作用,因为有一个小延迟,但是您将其移动到下一个循环。
实际上,您可以将延迟减少到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的风格,所以我个人更愿意坚持我的解决方案。
已解决问题 - 在重新加载数据后,我给endRefresh添加了一个微小的延迟:
[self.tableView reloadData];
[self.refreshControl performSelector:@selector(endRefreshing) withObject:nil afterDelay:0.05];
self.refreshControl.perform(#selector(UIRefreshControl.endRefreshing), with: nil, afterDelay: 0)
- Jordan HSwift 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
调用放在 else 关闭之后。这样可以使您的代码更加简洁易读。此外,如果您仅对开发过程中的错误原因感兴趣(不应该这样),您可以简单地反转 if 语句,并且可以使用更少的代码。 - Julian F. WeinerttableView.reloadData()
之前运行refreshControl?.endRefreshing()
。refreshControl?.endRefreshing()
tableView.reloadData()
endRefreshing()
在调用reloadData()
之后时,每当数据重新加载时,TableView都会跳动。tableView
完成重新加载的同时调用endRefreshing()
会导致弹跳/闪烁故障。我尝试了其他答案中提到的使用OperationQueue
和performSelector
的选项,但它们没有为我提供其他应用程序中看到的控制或平滑度。
相反,我选择了这个针对Swift和我的特定情况更新的解决方案:UIView.animate(withDuration: self.refreshControl.isRefreshing ? 0.5 : 0) {
self.refreshControl.endRefreshing()
} completion: { finished in
self.tableView.reloadData()
}
[refreshControl endRefreshing]
完成块的表格视图周围提交CATransaction将导致非常平滑的动画。我承认这感觉像是一个hack,因为据我所知[tableView reloadData]
是无法动画化的,但这是我特定情况下唯一可行的解决方案。 - Chrisself.refreshControl.perform(#selector(UIRefreshControl.endRefreshing), with: nil, afterDelay: 0)
- Jordan H