Используйте RefreshControl для асинхронного обновления

Я использую AFNetworking для загрузки некоторых данных из API, чтобы обновить UITableView. Я бы хотел, чтобы контроллер обновления отражал это как таковое.

  1. Пользователь тянет вниз и появляется колесо обновления

  2. Вызов API выходит (асинхронный вызов)

  3. Вызов API возвращает успех или ошибку

  4. UITableViewController завершает обновление, перезагружает данные, и колесо обновления исчезает

Поэтому я добавляю элемент управления обновлением в viewDidLoad моего пользовательского UIViewController (мое табличное представление является подвидом этого основного представления), как показано ниже:

//Set up refresh controller
    tableController = [[UITableViewController alloc]init];
    tableController.view = self.subscriptionsTable;
    UIRefreshControl* refresh = [[UIRefreshControl alloc]init];
    [refresh addTarget:self action:@selector(loadSubscriptions) forControlEvents:UIControlEventAllEvents];
    tableController.refreshControl = refresh;

Затем у меня есть свой метод обновления: (все, что делает [connections asyncCall:self], это отправляет асинхронный вызов API через модуль AFNetworking, вызывая завершенный метод моего контроллера представления, когда это сделано)

-(void)loadSubscriptions{
    updated = YES;
    [connections asyncCall:self];
}

Завершенные методы контроллеров представления выглядят так

-(void)asyncDone(id)responseObject{
    tableData = responseObject;
    NSLog(@"Yay, I'm done!");
}

К сожалению, управление обновлением завершается, конечно же, в ту же минуту, когда асинхронный вызов отправляется, а не когда он завершается, оставляя меня без обновленных данных. Как я могу заставить эту штуку немного повиснуть, пока асинхронный вызов не будет фактически завершен?


person steventnorris    schedule 28.08.2014    source источник


Ответы (1)


Вам нужно вызвать beginRefreshing и endRefreshing, когда начинается и заканчивается ваш асинхронный вызов. Для этого вам также потребуется сохранить ссылку на элемент управления refresh.

Итак, в loadSubscriptions и asyncDone::

-(void)loadSubscriptions{
    [self.refreshControl beginRefreshing];

    updated = YES;
    [connections asyncCall:self]; 
}

-(void)asyncDone(id)responseObject{
    tableData = responseObject;
    NSLog(@"Yay, I'm done!");

    [self.refreshControl endRefreshing];
}

Примечание. Многие асинхронные методы вызывают свой блок завершения в фоновом потоке, поэтому вам может потребоваться отправить этот endRefreshing вызов в основной поток:

dispatch_async(dispatch_get_main_queue(), ^{
    [self.refreshControl endRefreshing];
});
person Mike S    schedule 28.08.2014
comment
Это отлично сработает, когда я хочу вручную запустить обновление, но как насчет того, когда они отключаются? Это автоматически запускает начальное обновление, вызывает мой метод loadSubscriptions, а затем вызывает endRefreshing, когда оно завершается, правильно? - person steventnorris; 29.08.2014
comment
Мне нужно проверить это, чтобы быть уверенным, но я не думаю, что ручное нажатие запускает beginRefreshing само по себе; Я думаю, вам все равно придется вызывать его вручную. - person Mike S; 29.08.2014
comment
В документах указано: Элемент управления не инициирует операцию обновления напрямую. Вместо этого он отправляет событие UIControlEventValueChanged, когда должна произойти операция обновления. Вы должны назначить метод действия для этого события и использовать его для выполнения любых необходимых действий. Я знаю, что это прямо говорит о том, какую операцию вам нужно выполнить, чтобы обновить данные вашего табличного представления, но я думаю, что это также подразумевает, что вы еще нужно позвонить begin/endRefreshing. - person Mike S; 29.08.2014
comment
Вы правы похоже. AFNetworking обрабатывает вызов завершения в предварительно упакованном основном потоке, поэтому мне не нужно об этом беспокоиться. Спасибо за образование. - person steventnorris; 29.08.2014