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就会跳转。
当我的数据加载完成并且我的 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就会跳转。