[英]Running NSURLSession completion handler on main thread
我使用NSURLSession来获取填充TableView的值。 我正在完成处理程序中更新TableView,但使用[[NSThread currentThread] isMainThread]
向我显示完成处理程序未在主线程中运行。 由于我只应该从主线程更新UI,我知道这是不正确的。 有没有办法从完成处理程序触发主线程上的操作? 或者使用NSURLSession以错误的方式去做这个?
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:@"http://myurl"]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSError *jsonError = nil;
NSArray* jsonUsers = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
if (jsonError) {
NSLog(@"error is %@", [jsonError localizedDescription]);
// Handle Error and return
return;
}
self.userArray = jsonUsers;
[self.userTableView reloadData];
if ([[NSThread currentThread] isMainThread]){
NSLog(@"In main thread--completion handler");
}
else{
NSLog(@"Not in main thread--completion handler");
}
}] resume];
是的,只需使用GCD
调度您的主要线程:
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:@"http://myurl"]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSError *jsonError = nil;
NSArray* jsonUsers = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
if (jsonError) {
NSLog(@"error is %@", [jsonError localizedDescription]);
// Handle Error and return
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
self.userArray = jsonUsers;
[self.userTableView reloadData];
if ([[NSThread currentThread] isMainThread]){
NSLog(@"In main thread--completion handler");
}
else{
NSLog(@"Not in main thread--completion handler");
}
});
}] resume];
@graver的答案很好。 这是你可以做到的另一种方式:
NSURLSession* session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
delegate:nil
delegateQueue:[NSOperationQueue mainQueue]];
[[session dataTaskWithURL:[NSURL URLWithString:@"http://myurl"]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSError *jsonError = nil;
NSArray* jsonUsers = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
if (jsonError) {
NSLog(@"error is %@", [jsonError localizedDescription]);
// Handle Error and return
return;
}
self.userArray = jsonUsers;
[self.userTableView reloadData];
if ([[NSThread currentThread] isMainThread]){
NSLog(@"In main thread--completion handler");
}
else{
NSLog(@"Not in main thread--completion handler");
}
}] resume];
这样,您可以创建一个会话,该会话在主线程上调用完成块和任何委托方法。 您可能会发现这在美学上更令人愉悦,但您确实失去了在后台运行“艰苦工作”的优势。
这是从块和完成处理程序更新UI的最佳方法,也是在您没有确定运行代码的哪个线程时。
static void runOnMainThread(void (^block)(void))
{
if (!block) return;
if ( [[NSThread currentThread] isMainThread] ) {
block();
} else {
dispatch_async(dispatch_get_main_queue(), block);
}
}
这是一个静态方法,它将有一个块,并将在主线程上运行,它将像一个
runOnMainThread(^{
// do things here, it will run on main thread, like updating UI
});
你可以试试这个:
[self.userTableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
在完成后发送一个通知,表视图控制器将观察该通知,然后执行reloadData;
这样做的好处是,如果稍后将此下载代码移到单独的类(例如模型对象),则不需要进行任何更改,并且代码可以在其他项目中重用而无需进行更改
Swift 3.1
DispatchQueue.main.async {
tableView.reloadData()
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.