IOS:主线程后台操作过程中放缓

问题描述:

我使用下面的代码进行什么,我想成为一个后台同步,但主线程放缓甚至即将停止时收到的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

你只是做了一些多余的事情。您在后台线程中调度了数据的提取。但后来你也在后台线程中做了[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]; 
       }); 

因为你只应做任何修改,以在主线程UI。我的代码的这一部分正在主线程中完成这项工作。

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

我正在对此进行标记,因为它着重于在后台线程中重新加载数据,这是问题所在。根本没有理由在这里重新加载数据,因为直到所有新数据被下载和解析的最后才会重新加载。我也投了一些其他答案,指出提取数据(解析数据但不会立即影响UI)应该在同一个线程中。 – zztop

您不需要对同一个队列进行嵌套调用。你也应该在主线程上做任何UI工作。欲了解更多信息,看看苹果的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. 

有你的原代码的几个错误,更改为以下:

#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下。