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

ott*_*ter 24 cocoa multithreading ios ios7

我使用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];
Run Code Online (Sandbox Code Playgroud)

gra*_*ver 41

是的,只需使用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];
Run Code Online (Sandbox Code Playgroud)


bug*_*oaf 19

@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];
Run Code Online (Sandbox Code Playgroud)

这样,您可以创建一个会话,该会话在主线程上调用完成块和任何委托方法.您可能会发现这在美学上更令人愉悦,但您确实失去了在后台运行"艰苦工作"的优势.

  • Swift: `let session = NSURLSession(configuration: .defaultSessionConfiguration(), delegate: nil, delegateQueue: NSOperationQueue.mainQueue())` (4认同)