UIRefreshControl – 当UITableViewController位于UINavigationController中时,beginRefreshing不工作
我已经在我的UITableViewController(这是一个UINavigationController内)设置一个UIRefreshControl和它按预期的方式工作(即拉下来触发正确的事件)。 但是,如果我以编程方式调用刷新控件上的beginRefreshing
实例方法,如:
[self.refreshControl beginRefreshing];
什么都没发生。 它应该animation下来,并显示微调。 刷新后调用endRefreshing
方法时可以正常工作。
我用这种行为掀起了一个基本的原型项目,它正常工作时,我的UITableViewController直接添加到应用程序委托的根视图控制器,例如:
self.viewController = tableViewController; self.window.rootViewController = self.viewController;
但是,如果我首先添加tableViewController
到一个UINavigationController,然后添加导航控制器作为rootViewController
, beginRefreshing
方法不再起作用。 例如
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tableViewController]; self.viewController = navController; self.window.rootViewController = self.viewController;
我的感觉是,这与导航控制器中的嵌套视图层次结构有关,不能很好地进行复习控制 – 任何build议?
谢谢
看来,如果你开始以编程方式刷新,你必须自己滚动表格视图,比如说,通过改变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)
UITableViewController在iOS 7后自动调用ScrollViewInsets属性。表视图可能已经有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];
这是一个使用上述策略的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() } }
没有其他答案为我工作。 他们会导致微调显示和旋转,但刷新行动本身不会发生。 这工作:
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];
注意,这个例子使用了一个表格视图,但它也可以是一个集合视图。
已经提到的方法:
[self.refreshControl beginRefreshing]; [self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES];
会让纺纱工看得见 但它不会animation。 我改变的一件事是这两种方法的顺序,一切都奏效了:
[self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES]; [self.refreshControl beginRefreshing];
另见这个问题
调用beginRefreshing和contentOffset为0时,UIRefreshControl不显示棘手
它看起来像一个bug,因为它只发生在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){ }]; } }
这对我来说是完美的:
Swift 3:
self.tableView.setContentOffset(CGPoint(x: 0, y: -self.refreshControl!.frame.size.height - self.topLayoutGuide.length), animated: true)
除了@Dymitry舍甫琴科的解决scheme。
我发现这个问题很好的解决方法。 您可以创build扩展到覆盖方法的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中为界面构build器中的刷新控制设置自定义类来使用新类。
斯威夫特堡2.2+
self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.frame.size.height), animated: true)
如果您使用Rxswift为快速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。
我使用相同的技术来显示用户“数据是更新”的可视标志。 结果用户从后台带来的应用程序和饲料/列表将更新与用户界面像用户拉桌子刷新自己。 我的版本包含3件事情
1)谁发“唤醒”
- (void)applicationDidBecomeActive:(UIApplication *)application { [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationHaveToResetAllPages object:nil]; }
2)UIViewController中的观察者
- (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]; } }
这里是Swift 3的扩展,它显示了微调以及animation。
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() } } }