思い立ったが吉日!

iOSが好きです。

GCDを使って並列非同期通信

GCDの並列非同期通信

GCDの並列非同期処理を行います。

非同期通信

NSURL *url = [NSURL URLWithString:@"http://www.apple.com"];
    // UI変更用にmainThreadを準備
    dispatch_queue_t main = dispatch_get_main_queue();
    // 並列のディスパッチキューを準備
    dispatch_queue_t sub = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    // 並列のディスパッチキューで非同期処理
    dispatch_async(sub, ^{
        // 並列非同期で通信メソッドの実行
        [RequestManager sendAsynchronousRequest:url completionHandler:^(NSURLResponse *response, NSError *connectionError) {
            if (connectionError) {
                NSLog(@"nooaonoaaa!1!!!%@",connectionError);
            } else {
                dispatch_async(main, ^{
                    // UIの変更はmainで行う
                    self.textView.text = [NSString stringWithFormat:@"%@",response];
                    
                });
            }
            
        }];
        // この処理は処理通信より先に実行される
       NSLog(@"通信中");
    });

通信メソッド

+ (void) sendAsynchronousRequest:(NSURL*) requestURL completionHandler:(void (^)(NSURLResponse* response, NSError* connectionError))handler
{
    // SessionTaskの準備(resume呼ぶまで通信開始はしないので注意)
    NSURLSessionTask * task = [[NSURLSession sharedSession] dataTaskWithURL:requestURL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error)
    {
        // errorがnullだったら通信成功してるので結果を返す
        if (!error) {
            handler(response, error);
        }
    }];
    // 5秒待つ
    sleep(5);
    // 通信の開始    
    [task resume];
}

これを実行すると(通信成功するのを前提)

まず、通信用のメソッドsendAsynchronousRequestが呼ばれ、通信準備が非同期で行われる。

並列非同期なので、sendAsynchronousRequestの次の処理である、Logを出す処理も別スレッドで開始される。

この時sendAsynchronousRequest内のBlocksの式の部分(if else)が実行されたりはしないので注意。なぜなら、Blocksの式の部分の実行はsendAsynchronousRequest内のhandler()によってるから。

通信メソッド側の処理は、SessionTaskを生成し、5秒待つ処理があるので5秒待つ。

この間にLogは出す処理は終わってる。通信処理メソッド側は、5秒待ち終えたら通信の開始。

Blocks部分は同期的に処理されていくのでdataTaskWithURLからcompletionHandlerをが実行されるまで実行されない。

通信が終了しコールバックを得たら、dataTaskWithURLのBlocks内の式の部分が実行される。

sendAsynchronousRequestにコールバックが送られたらsendAsynchronousRequestのBlocksの式の部分が実行される。

メインスレッドからUIの変更を行う。

用意しておいたtextViewに通信結果が表示される。