我在我的UITableViewController(在UINavigationController中)设置了一个UIRefreshControl,它按预期工作(即下拉触发正确的事件)。但是,如果我以编程方式在刷新控件上调用beginRefreshing
实例方法,如:
[self.refreshControl beginRefreshing];
什么都没发生。它应该动画下来并显示微调器。当我在刷新后调用它时,endRefreshing
方法正常工作。
我用这种行为掀起了一个基本的原型项目,当我的UITableViewController直接添加到应用程序委托的根视图控制器时它可以正常工作,例如:
self.viewController = tableViewController;
self.window.rootViewController = self.viewController;
但是,如果我首先将tableViewController
添加到UINavigationController,然后将导航控制器添加为rootViewController
,beginRefreshing
方法将不再有效。 E.g。
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tableViewController];
self.viewController = navController;
self.window.rootViewController = self.viewController;
我的感觉是这与导航控制器中的嵌套视图层次结构有关,不能与复习控件一起使用 - 任何建议?
谢谢
答案 0 :(得分:175)
似乎如果以编程方式开始刷新,则必须自己滚动表格视图,例如,通过更改contentoffset
[self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:YES];
我猜这是因为当用户位于表格视图的中间/底部时,滚动到刷新控件是不可取的?
@muhasturk的Swift 2.2版本
self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.frame.size.height), animated: true)
简而言之,要保持此便携性,请添加此扩展程序
<强> UIRefreshControl + ProgramaticallyBeginRefresh.swift 强>
extension UIRefreshControl {
func programaticallyBeginRefreshing(in tableView: UITableView) {
beginRefreshing()
let offsetPoint = CGPoint.init(x: 0, y: -frame.size.height)
tableView.setContentOffset(offsetPoint, animated: true)
}
}
答案 1 :(得分:76)
UITableViewController在iOS 7之后有 automaticAdjustsScrollViewInsets 属性。表视图可能已经有contentOffset,通常是(0,-64)。
因此,在编程开始刷新后显示refreshControl的正确方法是将refreshControl的高度添加到现有的contentOffset。
[self.refreshControl beginRefreshing];
[self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES];
答案 2 :(得分:30)
这是使用上述策略的Swift扩展程序。
extension UIRefreshControl {
func beginRefreshingManually() {
if let scrollView = superview as? UIScrollView {
scrollView.setContentOffset(CGPoint(x: 0, y: scrollView.contentOffset.y - frame.height), animated: true)
}
beginRefreshing()
}
}
答案 3 :(得分:13)
其他答案都不适合我。它们会导致微调器显示和旋转,但刷新操作本身永远不会发生。这有效:
id target = self;
SEL selector = @selector(example);
// Assuming at some point prior to triggering the refresh, you call the following line:
[self.refreshControl addTarget:target action:selector forControlEvents:UIControlEventValueChanged];
// This line makes the spinner start spinning
[self.refreshControl beginRefreshing];
// This line makes the spinner visible by pushing the table view/collection view down
[self.tableView setContentOffset:CGPointMake(0, -1.0f * self.refreshControl.frame.size.height) animated:YES];
// This line is what actually triggers the refresh action/selector
[self.refreshControl sendActionsForControlEvents:UIControlEventValueChanged];
注意,此示例使用表视图,但它也可以是集合视图。
答案 4 :(得分:11)
已经提到的方法:
[self.refreshControl beginRefreshing];
[self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES];
会使微调器可见。但它不会有动画。我改变的一件事是这两种方法的顺序和一切都有效:
[self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES];
[self.refreshControl beginRefreshing];
答案 5 :(得分:7)
另见这个问题
UIRefreshControl not showing spiny when calling beginRefreshing and contentOffset is 0
对我来说这看起来像个错误,因为只有当tableView的contentOffset属性为0时才会发生错误
我用以下代码修改了它(UITableViewController的方法):
- (void)beginRefreshingTableView {
[self.refreshControl beginRefreshing];
if (self.tableView.contentOffset.y == 0) {
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^(void){
self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);
} completion:^(BOOL finished){
}];
}
}
答案 6 :(得分:5)
现有答案的混合为我做的工作:
refreshControl.beginRefreshing()
tableView.setContentOffset(CGPoint(x: 0, y: tableView.contentOffset.y - (refreshControl.frame.size.height)), animated: true)
希望这有帮助!
答案 7 :(得分:4)
这对我来说很完美:
斯威夫特3:
self.tableView.setContentOffset(CGPoint(x: 0, y: -self.refreshControl!.frame.size.height - self.topLayoutGuide.length), animated: true)
答案 8 :(得分:4)
这是Swift 3扩展,它显示了微调器以及动画。
import UIKit
extension UIRefreshControl {
func beginRefreshingWithAnimation() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
if let scrollView = self.superview as? UIScrollView {
scrollView.setContentOffset(CGPoint(x: 0, y: scrollView.contentOffset.y - self.frame.height), animated: true)
}
self.beginRefreshing()
}
}
}
答案 9 :(得分:3)
除了@Dymitry Shevchenko解决方案。
我找到了解决此问题的好方法。您可以创建覆盖方法的UIRefreshControl
扩展名:
// Adds code forgotten by Apple, that changes content offset of parent scroll view (table view).
- (void)beginRefreshing
{
[super beginRefreshing];
if ([self.superview isKindOfClass:[UIScrollView class]]) {
UIScrollView *view = (UIScrollView *)self.superview;
[view setContentOffset:CGPointMake(0, view.contentOffset.y - self.frame.size.height) animated:YES];
}
}
您可以通过在 Identity Inspector 中设置自定义类来使用新类,以便在Interface Builder中进行刷新控制。
答案 10 :(得分:3)
Fort Swift 2.2 +
self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.frame.size.height), animated: true)
答案 11 :(得分:3)
如果您使用Rxswift for swift 3.1,可以使用以下内容:
func manualRefresh() {
if let refreshControl = self.tableView.refreshControl {
self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.height), animated: true)
self.tableView.refreshControl?.beginRefreshing()
self.tableView.refreshControl?.sendActions(for: .valueChanged)
}
}
适用于swift 3.1,iOS 10。
答案 12 :(得分:1)
在Swift 5上进行了测试
在viewDidLoad()
fileprivate func showRefreshLoader() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.contentOffset.y - (self.refreshControl.frame.size.height)), animated: true)
self.refreshControl.beginRefreshing()
}
}
答案 13 :(得分:0)
我对show user“data is update”视觉符号使用相同的技术。结果用户从后台带来应用程序,并且将使用UI更新提要/列表,例如用户拉表以刷新自己。我的版本包含3件事
1)谁发送“醒来”
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationHaveToResetAllPages object:nil];
}
2)UIViewController中的Observer
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(forceUpdateData) name:kNotificationHaveToWakeUp:nil];
}
3)协议
#pragma mark - ForcedDataUpdateProtocol
- (void)forceUpdateData {
self.tableView.contentOffset = CGPointZero;
if (self.refreshControl) {
[self.refreshControl beginRefreshing];
[self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:YES];
[self.refreshControl performSelector:@selector(endRefreshing) withObject:nil afterDelay:1];
}
}
答案 14 :(得分:0)
对于Swift 5,对我来说唯一缺少的是打电话给refreshControl.sendActions(.valueChanged)
。我进行了扩展,使其更加整洁。
extension UIRefreshControl {
func beginRefreshingManually() {
if let scrollView = superview as? UIScrollView {
scrollView.setContentOffset(CGPoint(x: 0, y: scrollView.contentOffset.y - frame.height), animated: false)
}
beginRefreshing()
sendActions(for: .valueChanged)
}
}