UIRefreshControl - beginRefreshing не работает, когда UITableViewController находится внутри UINavigationController
Я установил UIRefreshControl в моем UITableViewController (который находится внутри UINavigationController), и он работает так, как ожидалось (т. е. вытаскивает правильное событие). Однако, если я программно вызываю beginRefreshing метод экземпляра на элементе управления обновлением, например:
[self.refreshControl beginRefreshing];
ничего не происходит. Он должен анимировать вниз и показать спиннер. Элемент 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;
Я чувствую, что это как-то связано с вложенными иерархиями представлений в навигационном контроллере, которые не играют хорошо с управлением обновлением - есть предложения?
спасибо
13 ответов:
кажется, что если вы начинаете обновление программно, вы должны прокрутить представление таблицы самостоятельно, скажем, изменив contentoffset
[self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:YES];Я бы предположил, что причина этого заключается в том, что может быть нежелательно прокручивать элемент управления обновлением, когда пользователь находится в середине/нижней части таблицы?
Swift 2.2 версия от @muhasturk
self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.frame.size.height), animated: true)в двух словах, чтобы держать этот портативный добавить расширение
UIRefreshControl + ProgramaticallyBeginRefresh.Свифт
extension UIRefreshControl { func programaticallyBeginRefreshing(in tableView: UITableView) { beginRefreshing() let offsetPoint = CGPoint.init(x: 0, y: -frame.size.height) tableView.setContentOffset(offsetPoint, animated: true) } }
UITableViewController и automaticallyAdjustsScrollViewInsets свойство после iOS 7. Табличное представление может уже иметь 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];сделает прядильщик видимым. Но это не будет оживлять. Единственное, что я изменил порядок этих двух методов, и все работало:
[self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES]; [self.refreshControl beginRefreshing];
Смотрите также этот вопрос
UIRefreshControl не показывает колючий при вызове beginRefreshing и contentOffset 0
это похоже на ошибку для меня, потому что это происходит только тогда, когда свойство contentOffset tableView равно 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)
вот расширение Swift 3, которое показывает spinner, а также анимирует его.
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() } } }
в дополнение к решению @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.
Форт Свифт 2.2+
self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.frame.size.height), animated: true)
Если вы используете Rxswift для 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.
Для Swift 4/4.1
сочетание существующих ответов сделать работу за меня:
refreshControl.beginRefreshing() tableView.setContentOffset(CGPoint(x: 0, y: tableView.contentOffset.y - (refreshControl.frame.size.height)), animated: true)надеюсь, что это помогает!
Я использую ту же технику для показа пользователю визуального знака "данные-это обновление". Результат пользователь приносит приложение из фона и каналов / списков будет обновляться с помощью пользовательского интерфейса, как пользователи тянут таблицы, чтобы обновить себя. Моя версия содержит 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]; } }

Comments