LoginSignup
41
43

More than 5 years have passed since last update.

NSURLSessionのsharedSessionでは、completionHandlerはmain threadで実行されない

Posted at

iOS7からNSURLSessionという新しいクラスが追加された。
通信周りの処理がNSURLConnectionより充実簡単になったのと、バックグラウンド処理が使えるようになったらしい。
ということで、試しに使ってみたらつまらないところでハマったのでメモ。

completionHandlerの中でUITableView:reloadを走らせようとしたら挙動がおかしくなった。
cellForRowAtIndexPathがすぐに呼ばれず、テーブルビューがスクロールされるタイミングで呼ばれる。

NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:@"http://hogefuga.com"];
[[session dataTaskWithURL:url
        completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            [_tableView reloadData];
        }] resume];

原因は、completionHandlerがmain threadで実行されてなかったからでした。
UIに変更を加える処理はmain threadで実行する必要があります。

blockの中にブレークポイントしかけると
スクリーンショット 2014-02-07 11.09.38.png
SerialQueueですね。

取り急ぎ、dispatch_get_main_queueで囲ってやればmain threadで実行されるようになる。

NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:@"http://hogefuga.com"];
[[session dataTaskWithURL:url
        completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [_tableView reloadData];
            });
        }] resume];

そういえば、NSURLConnectionはどうだったっけ?と思い振り返ると

NSURL *URL = [NSURL URLWithString:@"http://hogefuga.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];

[NSURLConnection sendAsynchronousRequest:request
                                   queue:[NSOperationQueue mainQueue]
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                           [_tableView reloadData];
                       }];

[NSOperationQueue mainQueue]で指定していました。
では、NSURLSessionでも指定できるのでは無いかと思い、調べたらありました。

NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

NSURL *url = [NSURL URLWithString:@"http://hogefuga.com"];
[[session dataTaskWithURL:url
        completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            [_tableView reloadData];
        }] resume];

sharedSessionはデフォルトの設定が適用されるらしいです
仕組みを理解してから使うべきでした。
反省しました。

41
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
43