在主线程上运行NSURLSession完成处理程序

我正在使用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]; 

这样你就可以创build一个会话,调用主线程上的完成块和任何委托方法。 你可能会觉得这更美观,但你却失去了在后台运行“努力工作”的优势。

你可以试试这个:

 [self.userTableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO]; 

这里是从块和完成处理程序更新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 }); 

发送完成通知将由表视图控制器,然后将执行一个reloadData观察;

这样做的好处是,如果稍后将此下载代码移到单独的类(例如模型对象)中,则不需要进行任何更改,而且代码可以在其他项目中重用,而无需进行更改

Swift 3.1

 DispatchQueue.main.async { if (Thread.isMainThread) { tableView.reloadData() } }