Обновление содержимого UITableView замораживает приложение

У меня проблема при обновлении данных в моем UITableview. В настоящее время есть UIRfreshControl, который при срабатывании (путем вытягивания вниз) выполняет следующее:

- (void)refreshByScrolling:(UIRefreshControl *)refreshControl {
    [self refreshPriceInformation];
    [refreshControl endRefreshing];
}

В этот момент пользовательский интерфейс зависает (за исключением вращающегося элемента refreshControl, пока метод [self refreshPriceInformation] не будет завершен.

Есть ли способ сделать так, чтобы пользовательский интерфейс не зависал при обновлении данных? Например, в приложениях Twitter и Instagram вы можете потянуть вниз, чтобы обновить и сразу после этого начать прокручивать таблицу вниз.

Код для [self refreshPriceInformation] приведен ниже.

-(void)refreshPriceInformation
{

isRefreshing = true;

//Creating Queues for Concurrent refreshes
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);


dispatch_apply([watchedSkinList count], queue, ^(size_t i) {

        SkinToWatch *watchedSkin =[watchedSkinList objectAtIndex:i];
        [watchedSkin refreshPriceInformation];

});

 dispatch_async(queue, ^{
     NSLog(@"Saving Data to Phone");

     // resaving data to phone
     NSData *newdata = [NSKeyedArchiver archivedDataWithRootObject:watchedSkinList];
     [[NSUserDefaults standardUserDefaults] setObject:newdata forKey:@"watchSkinsArray"];
     [[NSUserDefaults standardUserDefaults]synchronize ];


    isRefreshing = false;
     [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];

     //Updating Refresh Label
     [self updateDateAndSaveDurning:false];

 });



}

Спасибо!

РЕДАКТИРОВАТЬ ***** Как заявил HackerInHeels ниже, обертывание dispatch_apply с DISPATCH_QUEUE_PRIORITY_BACKGROUND предотвратило зависание пользовательского интерфейса!

Дополнительные вопросы: 1) как убедиться, что этот блок кода выполняется последним?

dispatch_async(queue, ^{
         NSLog(@"Saving Data to Phone");

//rest of code...
});

Перед внедрением решения это был последний блок, который нужно было выполнить. После решения это уже не так. Я ставлю в него еще одну очередь? Сделать синхронизацию, а не aysnc?

Спасибо еще раз!


person p0ny    schedule 17.07.2014    source источник


Ответы (2)


Можете ли вы попробовать это для меня ..

Оберните код SkinToWatch в dispatch_async

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    dispatch_apply([watchedSkinList count], queue, ^(size_t i) {

    SkinToWatch *watchedSkin =[watchedSkinList objectAtIndex:i];
    [watchedSkin refreshPriceInformation];

    });
});
person hackerinheels    schedule 17.07.2014
comment
Кажется, это удалось! Спасибо. Кроме того, вы случайно не знаете, куда поместить код, если я хочу обновить пользовательский интерфейс отдельных ячеек во время обновления? Чтобы я мог активировать индикатор активности? - person p0ny; 18.07.2014
comment
отличный! данные ячейки обновляются в cellForRowAtIndexPath - когда ваша базовая модель данных изменяется, вызовите reloadData, и это должно вызвать функции делегата tableview, которые должны смотреть на обновленную модель данных.. поэтому вам не нужно делать что-либо еще, кроме reloadData. если это не отвечает на ваш вопрос, пожалуйста, обновите вопрос выше или создайте новый, и я посмотрю - person hackerinheels; 18.07.2014
comment
почему бы вам не поместить этот фрагмент кода после [watchedSkin RefreshPriceInformation]; в том же блоке кода - person hackerinheels; 18.07.2014
comment
Я не думаю, что этот фрагмент кода будет работать после [watchedSkin refreshPriceInformation]. Это потому, что мне нужно дождаться обновления всей информации о ценах для каждого скина, прежде чем сохранять на телефон. надеюсь это имело смысл - person p0ny; 18.07.2014
comment
он обновляется в refreshPriceInformation? Если да, то почему бы вам не передать блок кода сохранения на диск в качестве параметра функции refreshPriceInformation. Эта функция возьмет блок кода и выполнит его, если обновление прошло успешно, в противном случае она может его проигнорировать. - person hackerinheels; 18.07.2014
comment
Неважно, я просто ошибся в том, что ты сказал. Я просто переместил этот блок внутрь DISPATCH_QUEUE_PRIORITY_BACKGROUND и поместил его ниже dispatch_apply и его работы. Спасибо за вашу помощь! - person p0ny; 18.07.2014
comment
Может ли кто-нибудь дать быстрое решение для этого? Я застрял с этим в течение многих часов! :( - person softdev; 07.11.2018

Попробуй это

dispatch_async(dispatch_get_main_queue(), ^{
        [self.tableView reloadData];

        }); 

вместо

[self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
person Nazim    schedule 17.07.2014
comment
Пользовательский интерфейс все еще зависает при попытке сделать это. Спасибо хоть - person p0ny; 18.07.2014