I am using a NSURLSession to get the values to populate a TableView. I am updating the TableView in the completion handler, but using [[NSThread currentThread] isMainThread]
has shown me that the completion handler isn't running in the main thread. Since I should only updating the UI from the main thread, I know this isn't correct. Is there a way to trigger an action on the main thread from the completion handler? Or is using a NSURLSession the wrong way to go about this?
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];
Yes, just dispatch your main thread stuff using 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's answer is good. Here's another way you can do it:
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];
This way you create a session that calls the completion block and any delegate methods on the main thread. You may find this more aesthetically pleasing, but you do lose the advantage of running the "hard work" in the background.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With