Подтвердить что ты не робот

Ошибка 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];
4b9b3361

Ответ 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, настроенного в раскадровке.