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

UIRefreshControl endRefreshing не является гладким

Когда мои данные завершили загрузку и мой tableView был перезагружен, я вызываю endRefreshing на моем контроле обновления, затем он "перескакивает" из состояния загрузки и исчезает - как я могу реализовать плавную анимацию, которая удаляет элемент управления обновлением, когда он завершен?

4b9b3361

Ответ 1

Я добавляю новый ответ, потому что единственный из них не очень точен в объяснении. И это, вероятно, будет слишком большим для комментариев.

Решение Halpo верное. Но указанная причина неверна.

Вызов -[NSObject (NSDelayedPerforming) performSelector:withObject:afterDelay:] гарантирует, что вызов будет выполнен в следующей итерации runloop.

Так что это не работает, потому что есть небольшая задержка, но вы переходите к следующему циклу.

Фактически вы можете уменьшить задержку до 0.0, и она все равно будет работать. Кроме того, возможно более правильное (с точки зрения использования объекта, предназначенного для достижения чего-то, а не лучшего результата).

Вот несколько фрагментов кода для этого:

// SOLUTION I

[[self tableView] reloadData];
[[self refreshControl] performSelector:@selector(endRefreshing) withObject:nil afterDelay:0.0];

// SOLUTION II (semantically correct)

[[self tableView] reloadData];
[[NSOperationQueue currentQueue] addOperationWithBlock:^{
    [[self refreshControl] endRefreshing];
}];

// SOLUTION III (GCD)

dispatch_async(dispatch_get_main_queue(), ^{
    [[self refreshControl] endRefreshing];
}];

ИЗМЕНИТЬ

Как отметил johann-fradj, вы также можете использовать GCD. Мне очень нравится GCD, но я думаю, что решение II наиболее описывает, что происходит. Кроме того, GCD не очень похож на Objective-C -ish, поэтому я лично предпочитаю использовать свое решение.

Ответ 2

Исправлена ​​проблема - я добавил небольшую задержку для endRefresh после перезагрузки данных:

[self.tableView reloadData];
[self.refreshControl performSelector:@selector(endRefreshing) withObject:nil afterDelay:0.05];

Ответ 3

Решение Swift 4

    tableView.reloadData()
    if refreshControl?.isRefreshing == true {
        DispatchQueue.main.async {
            self.refreshControl?.endRefreshing()
        }
    }

Другие решения (задержка, использующая CATransaction,...) более сложны и не дают никакого видимого преимущества

Ответ 4

Попробуйте обернуть вызов endRefreshing() в блоке анимации UIView:

Я столкнулся с этой проблемой. Для endRefreshing() В документации указано:

UIView.animateWithDuration(0.5) {
    self.refreshControl.endRefreshing()
}

В документации указано:

Если анимация также включена, элемент управления скрыт с помощью анимации.

Ответ 5

Одна из причин может заключаться в том, что вы обновляете представление таблицы после вызова endRefresh. Например, мои вызовы выглядели так:

[self.refreshControl beginRefreshing];
[self.network getThings:^(id things, NSError *error) {
    [self.refreshControl endRefreshing];

    if (error) {
        ...
    } else {
        self.things = things;
        [self.tableView reloadData];
    }
}];

Это плохо, потому что таблица обновляется, пока анимация endRefresh работает. Итак, код, сделанный правильно, выглядит так:

[self.refreshControl beginRefreshing];
[self.network getThings:^(id things, NSError *error) {
    if (error) {
        [self.refreshControl endRefreshing];
        ...
    } else {
        self.things = things;
        [self.tableView reloadData];
        [self.refreshControl endRefreshing];
    }
}];

Ответ 6

Решением для меня было запустить refreshControl?.endRefreshing() до вызова tableView.reloadData():

refreshControl?.endRefreshing()
tableView.reloadData()

Когда вызов к endRefreshing() был после вызова к reloadData(), TableView будет переходить при каждой перезагрузке данных.