Ошибка UIRefreshControl при входе на передний план
Я заметил небольшую ошибку (но очень раздражает), когда я использую UIRefreshControl
в моем контроллере просмотра. Когда приложение возвращается из фона, UIRefreshControl
уже загружен и выглядит следующим образом:
![]()
![]()
Как вы можете видеть, я использую настраиваемый контроллер навигации, который скрывается, как в приложении Facebook (AMScrollingNavBar
). Когда я перезагружаю данные в UITableView
, все возвращается к нормальному состоянию, и эта ошибка отображается только после возврата из фона.
Это код, который я использую для инициализации UIRefreshControl
в viewDidLoad
:
// Initializing generic refresh control
self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:@selector(collectData) forControlEvents:UIControlEventValueChanged];
[self.tableView addSubview:self.refreshControl];
Ответы
Ответ 1
Это известная ошибка в iOS7. Вы можете увидеть, как оно воспроизводится в приложении Apple mail. Я могу подтвердить, что он не был исправлен как iOS7.1 beta 5 iOS8.0 beta 3 iOS 10.0.1.
Сначала откройте отчет об ошибке в https://bugreport.apple.com/
Мое радиолокационное число rdar://14586451
, которое является дубликатом rdar://14493713
(все еще открытым).
Предлагаемое исправление заключается в регистрации уведомлений UIApplicationWillEnterForegroundNotification
в вашем контроллере представления и вызове [self.refreshControl.superview sendSubviewToBack:self.refreshControl];
, чтобы устранить проблему, указав, что элемент управления обновлением отображается за содержимым вашей таблицы.
Во втором скриншоте я вижу, что элемент управления обновлением отображается под вашей ячейкой. Вероятно, это связано с тем, что вы установили четкий цвет в качестве фона вашей ячейки. Установите его в белый цвет.
Ответ 2
Я нашел одно решение для изменения этой ошибки. Возможно, это тоже поможет вам. В моем приложении переход на другую вкладку и возврат к вкладке с помощью элемента управления обновлением сломал его - элемент управления больше не оживлялся при перетаскивании.
Вместо настройки UIRefreshControl в viewDidLoad я устанавливаю его в viewDidAppear, а затем всегда удаляю его в viewDidDisappear. Таким образом, он всегда инициализируется свежим и не путается.
Как и в предыдущем ответе на этот вопрос, я запросил UIApplicationDidBecomeActiveNotification, чтобы можно было также устранить элемент управления обновлением, когда пользователь переходит в приложение.
@implementation MYViewController {
UIRefreshControl *refreshControl;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
/* Pull down to refresh. iOS bug: If we add this in viewDidLoad and let it
* stay there for the lifetime of the view, the control will misbehave
* after going to another view/tab and coming back (will not animate nicely
* on drag).
*/
[self setupRefreshControl];
/* We'll want to be notified for didBecomeActive, to do the pull-down-to-refresh workaround when resuming. */
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(setupRefreshControl)
name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)setupRefeshControl
{
if (refreshControl)
[refreshControl removeFromSuperview];
refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(refreshPull:)
forControlEvents:UIControlEventValueChanged];
[scrollView addSubview:refreshControl];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[refreshControl removeFromSuperview];
refreshControl = nil;
/* We don't need notification for becoming active any more */
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
Немного субоптимальный, но работает.
Ответ 3
Эта ошибка возникает при создании модальной презентации над контроллером табличного представления, а также при возврате приложения из фона.
Самое простое решение - вызвать endRefreshing()
в viewWillAppear(_:)
и после получения уведомления UIApplicationWillEnterForeground
. Вам нужно сделать так, потому что viewWillAppear(_:)
не вызывается, когда приложение возвращается из фона.
Эффект вызова endRefreshing()
в экземпляре UIRefreshControl заключается в том, чтобы вернуть элемент управления в правильное расположение в иерархии представления и убедиться, что он продолжает правильно анимироваться при последующих обновлениях.
Не забудьте проверить, что ваш контроль обновления, по сути, не освежает.
В Swift:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
endRefreshing()
NotificationCenter.default.addObserver(self,
selector: #selector(endRefreshing),
name: Notification.Name.UIApplicationWillEnterForeground,
object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self,
name: Notification.Name.UIApplicationWillEnterForeground,
object: nil)
}
func endRefreshing(_ notification: Notification? = nil) {
if refreshControl?.isRefreshing == false {
refreshControl?.endRefreshing()
}
}
Протестировано в Xcode 7.0, ориентированном на iOS 8.0 с помощью UITableViewController, настроенного в раскадровке.