2016-05-16 2 views
0

Я использую следующий код, чтобы вести то, что я хочу быть фоновым синхронизацией, но основной поток замедляется или даже останавливается, когда json получает больше 20 или поэтому записи. Что-то не так с этим кодом для фоновой операции? Что может блокировать основной поток. Благодарим вас за любые предложения.IOS: основная нить замедляется во время фоновой операции

Обратите внимание, что приведенная ниже строка выполняет функцию performSelectorOnMainThread, где приложение обрабатывает полученное JSON, которое я изменил, на другой фоновый поток, но это изменение не помогает.

#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) //1 
#define kProductsURL [NSURL URLWithString: @"http://~/getproducts.php"] 

//in viewDidLoad 
if(hasInternet==YES && [loggedIntoServer isEqual:@1]) { 

     dispatch_async(kBgQueue, ^{ 
      NSData* data = [NSData dataWithContentsOfURL: kProductsURL]; 
       //previous line grabed data from api. 
      if (data) { 
     // [self performSelectorOnMainThread:@selector(fetchData:) withObject:data waitUntilDone:YES];//no longer doing this on main thread 
       dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
        [self fetchData:data]; 
       }); 

       } 
     }); 
       ; 
    } //close hasInternet, logged into server. 



    - (void)fetchData:(NSData *)jsonFeed { 
    NSError* error; 
    NSDictionary* json = [NSJSONSerialization JSONObjectWithData:jsonFeed 
                 options:kNilOptions 
                  error:&error]; 
    NSMutableArray* latestProducts = [[NSMutableArray alloc] init]; 
    //this is specific to format of JSON 
    if (![[json objectForKey:@“products"] isKindOfClass:[NSNull class]]) { 
      latestProducts = [[json objectForKey:@“products"]mutableCopy]; 
    getProducts = latestProducts; 
    int size = [latestProducts count]; 
    [self.tableView reloadData]; 
    getProducts = [self convertFeedtoObject:latestProducts]; 
    [self importAndSaveProducts:getProducts];//this imports and saves 
    self.recentlySynced=YES; 
    } 
} 
+0

где находится основная тема? –

+0

dispatch_get_global_queue не является основной нитью !!! –

+0

Мне нравится то, что делает ваш метод 'fetchData:'. И как вы создаете 'kBgQueue' – marosoaie

ответ

1

Вы только что сделали что-то избыточное. Вы отправили выборку данных в фоновом потоке. Но тогда вы также сделали [self.tableView reloadData]; в фоновом потоке. Вот почему ваш пользовательский интерфейс будет затронут.

Попробуйте это:

if(hasInternet==YES && [loggedIntoServer isEqual:@1]) 
{ 
    dispatch_async(kBgQueue,^
    { 
     NSData* data = [NSData dataWithContentsOfURL: kProductsURL]; 

     if (data) 
     { 
       dispatch_async(dispatch_get_main_queue(),^
       { 
        [self fetchData:data]; 
       }); 
     } 
    }); 
} 

То, что я сделал, я изменил эту часть кода:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
        [self fetchData:data]; 
       }); 

Потому что вы должны делать только какие-либо изменения в пользовательском интерфейсе в основном потоке. и эта часть моего кода выполняет работу в основном потоке.

dispatch_async(dispatch_get_main_queue(),^
        { 
         [self fetchData:data]; 
        }); 
+0

Я отмечаю это правильно, потому что он сфокусирован на перезагрузке данных в фоновом потоке, который был проблемой. Не было причин перезагружать данные здесь вообще, поскольку перезагрузка не должна происходить до самого конца, когда все новые данные были загружены и проанализированы. Я также проголосовал за некоторые другие ответы, в которых указывалось, что выборка данных (которая анализирует данные, но не влияет непосредственно на пользовательский интерфейс) должна быть в одном потоке. – zztop

1

Вам не нужно иметь вложенный вызов в ту же очередь. Также вы должны выполнить любой пользовательский интерфейс в основном потоке. Для получения дополнительной информации смотрите на Apple's Concurrency Programming Guide

В вашем методе fetchData загрузите таблицу таким образом.

dispatch_async(dispatch_get_main_queue(), { 
    // Your UI work 
    [self.tableView reloadData]; 

}) 


// Remove second dispatch_async call 

//in viewDidLoad 
if(hasInternet==YES && [loggedIntoServer isEqual:@1]) { 

     dispatch_async(kBgQueue, ^{ 
      NSData* data = [NSData dataWithContentsOfURL: kProductsURL]; 
       //previous line grabed data from api. 
      if (data) { 
       [self fetchData:data]; 

       } 
     }); 
       ; 
} //close hasInternet, logged into server. 
1

Есть несколько ошибок в исходном коде, изменить на следующее:

#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0) //CHANGE TO BACKGROUND 
#define kProductsURL [NSURL URLWithString: @"http://~/getproducts.php"] 

//in viewDidLoad 
if(hasInternet==YES && [loggedIntoServer isEqual:@1]) { 
     dispatch_async(kBgQueue, ^{ 
      NSData* data = [NSData dataWithContentsOfURL: kProductsURL]; 
      if (data) {    
       [self fetchData:data]; 
      } 
     }); 
    } //close hasInternet, logged into server. 

Изменение выборки данных на следующее:

- (void)fetchData:(NSData *)jsonFeed { 
    NSError* error; 
    NSDictionary* json = [NSJSONSerialization JSONObjectWithData:jsonFeed 
                 options:kNilOptions 
                  error:&error]; 

    NSMutableArray* latestProducts = [[NSMutableArray alloc] init]; 

    //this is specific to format of JSON 
    if (![[json objectForKey:@"products"] isKindOfClass:[NSNull class]]) { 

     latestProducts = [[json objectForKey:@"products"]mutableCopy]; 

     getProducts = latestProducts; 
     int size = [latestProducts count]; 

     //Do this on the main thread: 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self.tableView reloadData]; 
     }); 

     getProducts = [self convertFeedtoObject:latestProducts]; 
     [self importAndSaveProducts:getProducts];//this imports and saves 
     self.recentlySynced=YES; 
    } 
} 

В зависимости от того, как просмотреть работы таблицы и что такое источник данных, вы можете переместить строку представления таблицы перезагрузки (с отправкой главной очереди) под self.recentSynced = YES.

Смежные вопросы