[英]IOS: Main thread slowing down during background operation
我正在使用以下代码来进行我想成为后台同步的操作,但是当接收到的json大于20个左右记录时,主线程正在减慢速度甚至停止运行。 此代码的后台操作有什么问题吗? 什么可能会阻塞主线程。 感谢您的任何建议。
请注意,在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;
}
}
您无需对同一队列进行嵌套调用。 另外,您应该在主线程上执行任何UI工作。 有关更多信息,请参阅《 Apple 并发编程指南》。
在您的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.
您只是做了多余的事情。 您在后台线程中调度了数据获取。 但是随后您也做了[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];
});
您的原始代码中有几个错误,请更改为以下内容:
#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下方。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.