IOS非同期でデータを取得し、インタフェースdispatch_をリフレッシュasyncの使い方

6215 ワード

iosの開発と学習ではマルチスレッドプログラミングは必ず遭遇して使用しなければならない.
JavaやAndroidの開発では,多数のバックグラウンドで実行され,非同期メッセージキューは,基本的にマルチスレッドを用いて実現されている.同様にiosモバイル開発とAndroidでは基本的に似たモデルである.しかし、多くの場合、アプリケーション開発では、同時イベントを処理したり、新しいサブスレッドを開いたりするのに自分でコードしていないことがわかります.(一般的な呼び出しsdkはネットワークリクエストを開始しますが、システムは新しいスレッドをデフォルトで処理します).プログラム全体がほぼMainスレッドで実行されているように見えます.確かに、コントロールのレイアウトを操作したり、コントロールデータを追加したり、UIオブジェクトの更新をメインスレッドで行ったりする現象です.処理データを取得するために新しいサブスレッドを開いたのを見ても、UIプライマリ・スレッドに通知することでリフレッシュする必要があります.もちろんios自体もほとんどの言語と同じようにNSThreadスレッドクラスがあります(javaでこのクラスを使用していることはよく知られています).これらのシステムは最下位のapiクラスを比較して、私が自分の同時スレッドと操作キューを書くために使用することができます.Androidを学んだ私たちはHandler、Looperという概念を知っています.Looperは、メインスレッドのメッセージループキューであることを明らかにしました.handlerは、サブスレッドとUIメインスレッドのデータインタラクションに使用されることを一般的に理解しています.iosのGCD特性を見てみると、彼らの間にはいくつか似ていることが分かった.
1.gcdプログラミングの非同期化の使い方を見てみましょう
Objective-cコード
dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
    //           ... 
    //        
    dispatch_async(dispatch_get_main_queue(), ^{ 
        //             , 
    }); 
});

dispatch_asyncは非同期操作を開き、最初のパラメータはgcdキューを指定し、2番目のパラメータは物事を処理するブロックをキューに割り当てる.dispatch_get_global_Queue(0,0)は、グローバルキューが使用されていることを意味します.一般的にシステム自体には3つのキューがあります.global_queue,current_queue、main_Queue.グローバルキューを取得するのは2つのパラメータを受け入れることであり、1つ目は私が割り当てた物事ハンドラブロックキューの優先度である.高低とデフォルト、0はデフォルト2は高さ、-2は低
Objective-cコード
#define DISPATCH_QUEUE_PRIORITY_HIGH     2  
#define DISPATCH_QUEUE_PRIORITY_DEFAULT  0  
#define DISPATCH_QUEUE_PRIORITY_LOW     (-2) 

物事を処理した後、UIマスタースレッドに結果を返すか、リフレッシュする必要があります.同様に、上と同じように、マスタースレッドをキャプチャし、ブロック操作を行います.
二:GCDの同時概念
実はプログラミングでは、同期、非同期、同時、ロックなど、いくつかの概念について言及しています.急にはっきり言えないような気がすることがあります.
次に、上記の画像のロードでこの3つの概念を理解します.
1.同期:
Objective-cコード
for (int i = 0 ; i < 10; i++) {       
      UIImage *img = [self getImgeWith:[urlArr objectForIndex:i]];  
       [myImgV[i] setImage:img];         
}

10個のピクチャをロードするとします.私は今、これらのピクチャのリソースアドレスを持っていて、1つの配列に保存しています.まず、最初のピクチャを取得することを例に挙げます.同期実行の概念は、最初のピクチャを取得した後、forループの最初の文を実行してimgに戻った後、私は第2の文、UIインタフェースのリフレッシュを実行することができます.最初の文が戻るのに10秒かかると、私のプログラムの応答はずっとここに詰まっているように、他の操作はできません.戻ってくるのを待たなければならない!!そのため、同期の1つのとても理解しやすい感念は、一歩暗くなることです.
2.非同期
for (int i = 0 ; i < 10; i++) {  
      dispatch_async(dispatch_get_global_queue(0, 0), ^{  
      //           ...  
       UIImage *img = [self getImgeWith:[urlArr objectForIndex:i]];  
      //         
      dispatch_async(dispatch_get_main_queue(), ^{  
          //             ,  
          [myImgV[i] setImage:img];  
      });  
        
  });

このコードを見て、私たちは、非同期操作の仮定はまだ10秒かかりますが、全体的に見ると、1枚の画像を実行する時間のロードはやはり10秒ぐらいですね.非同期では鳥の役に立ちませんか.しかし、その中の1つを無視しないでください.黒い糸のコアの1つです.この时、私たちの画像取得操作はスレッドの列の中に置いてあります.今、私たちは画像のロードを見ても10秒かかりますが、この10秒の間、UIのメインスレッドは操作することができます.例えば、インタフェースにボタンがあります.あなたは上の同期ではなく、押すことができます.10面の間、私は待つしかありません.何もできません.非同期のコアコンセプトは、新しいスレッド、メッセージコールバック通知です.
3.並列
上記のコードを例に挙げます.前に強調したように、私たちは1枚の画像のロードだけを見て、今、私たちの最初のコードを見た思考に戻って、forサイクルです.実は上のコードの後、私は10個の非同期スレッドを作成しました.はい、ここで、私たちはこの3つの概念を理解しなければなりません.同期、実は私の前の例はいくつかの限界を挙げて、この例自体が同期実行を必要としないことを説明して、それからみんなに同期がプログラミングの中の1つのタブーのように感じさせて、実はそうではありませんて、多くの时.私たちは本当に同期していくつかの制限をする必要があります(例えば、スレッドで提案されている同期ロック?聞いていると役に立ちますか?私たちが思っているほど同期を運用するわけではありませんが、少なくともこの概念が同じように役に立つことを説明します)私はやはりさっきのロード画像を例に、同期を運用するメリットを簡単に説明します.もちろん、私は同期の状況をシミュレートしただけです.もし私たちが今画像のロードがこのようなものだとしたら、画像自体はロード前にデフォルトの画像で、上に書いてあります.私をクリックしてロードして、クリックした後にネットワークのロード方法を呼び出して、それから画像はロード中を表示して、それから私たちは画像をダブルクリックする時(もちろん、理論的にはロードが終わった後に)画像のネットワークの画像を読んで拡大して、いいでしょう.ここまで来ると表現したいことが考えられるはずです.全体の流れは、画像をクリックする->ロード->ダブルクリックして表示する必要があります.では、クリック->ロード中(画像の作成者と情報を返す)-』となって、画像をダブルクリック(前に要求された大きな図のリンクで大きな図を表示する)-」を完全にロードして戻ります(大きな図のリンクを返します).この時、画像の大きな図が見えなくなりました.私たちが操作する前に、つまり、多くの場合、私たちの次の動作の操作が前の操作のデータを使用する必要がある場合、私たちは彼にボタンロックを追加するなどの同期プログラミングをします.これは私たちがまた疑問に思っていることです.次の実行には前の実行が必要です.その最初の例のforループの2番目の文は使うのではないでしょうか.そう言えば、彼らは同期しなければなりません.そう思ったら、偶然にも、私たちは一緒に行きたいと思っています.しかし、前に着いた非同期は私が他のボタンをクリックした操作を解決するためです.UI操作を更新するわけではありません.UIのダウンロードと更新操作は、私たちから見れば同期しなければならないのは正しいが、それはシステム自体のリスニングイベントがクリック処理をリスニングすることを招いた.その要求の後、こちらのロード画像は実際にはイベント実行と見なされなければならない.イベントの抽象ユニットについては、実際には定義可能な広さであるからだ.すなわち、1回のデータ取得と画像充填は、実は1つの画像取得ロードイベントであり、イベントは2つのユニット、ロードと充填を含むと言える.このイベント全体が他のボタンをクリックしても関係ないので、同期する必要はありません.そうですね.しかし、もし私たちがこの画像をクリックしたら、さっきダブルクリックできる仮説に戻ります.ここで私はまた、なぜロード中にダブルクリックできるのかを無視したかもしれません.このような仮定では、画像を取得するのは非同期ですが、次の操作は同期が必要なので、人為的な同期ロックをしました.はい、言いすぎました.少なくとも2つの非同期は、どうせ時間がかかる操作によるプライマリ・スレッドの詰まりのためであり、同期は不要なエラーや面倒を解決するためである可能性があることを理解しました.ここまで来ると、いわゆるスレッドセキュリティを頭の中で連想するかもしれません.実は同期と同期ロックは、このような不要と不安全な要素を考慮しているはずです.
最後に,非同期と同時関係を簡単に述べる.実際には、上述したように、非同期はマルチスレッド処理の概念を提供しているだけで、同時は非同期の大規模な実現のようなものです.例えば、弟で保護費を受け取ることができて、教えて自分に渡すことができて、私はその間に他のことをします.同時に突然、非同期というのは理にかなっていると思います.じゃ、私は4つの場所を持っています.1人の弟が受け取りに行きます.私はまだ暇で他のことをすることができますが、弟は4つの場所を走っています.私がお金を手に入れるのに必要な時間は私自身と同じです.ただ、私はそんなに苦労しなくてもいいです.他のこともできます.そのため、4人の弟を派遣すべきだと思っています.場所ごとに保護費が関係ないからです.(ニューヨークのギャングを見たばかりです~).
従って,非同期はスレッド詰まりを解決し,同時は非同期に基づいて特性イベントに適合する処理時間効率を向上させる.
もちろん、10個のピクチャ自体が互いに関連していない場合は、最後のイベントは、10個のピクチャの総容量値を計算する処理を必要とする.ではdispatch_を使ってgroup_async. 具体的にはドキュメントを見てみましょう.
全体的にiosGCDを見て、一つはblockプログラミングの特性を熟知させ、iosが提供したGCD特性をどのように使ってマルチスレッドプログラミングを完成するかを熟知させたことです.
一般的な方法dispatch_async
ネットワークデータの読み取り、IO、データベースの読み書きなど、インタフェースが時間のかかる操作を処理するときに詰まってしまうのを避けるために、別のスレッドで処理し、メインスレッドにインタフェースの更新を通知します.
GCDでこの流れを実現する操作は,前述したNSThread NSOperationよりも簡単である.コードフレームワークは次のように構成されています.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  
    //        
    dispatch_async(dispatch_get_main_queue(), ^{  
        //       
    });  
}); 

まだはっきりしていない場合は、前の2つのブログのダウンロード画像を例に挙げます.コードは以下の通りです.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  
    NSURL * url = [NSURL URLWithString:@"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"];  
    NSData * data = [[NSData alloc]initWithContentsOfURL:url];  
    UIImage *image = [[UIImage alloc]initWithData:data];  
    if (data != nil) {  
        dispatch_async(dispatch_get_main_queue(), ^{  
            self.imageView.image = image;  
         });  
    }  
});