swift詳しく解く十七--------GCDのいくつかの高級な使い方


GCDのいくつかの高度な使い方 : GCD
1、Dispatch Group(スケジューリンググループ)
Dispatch Groupは、グループ全体のタスクが完了したときに通知します.これらのタスクは同期でも非同期でも、異なるキューでも実行できます.複数の非同期タスクの完了を監視する問題.これは間違いなくとても良い選択です.
監視されたタスクは異なるキューにある可能性があるため、dispatch_group_tの例でこれらの異なるタスクを記述する.
グループ内のすべてのイベントが完了すると、GCDのAPIは2つの通知方式を提供する.
1つ目はdispatch_group_waitで、グループ内のすべてのタスクが完了するか、タイムアウトが発生するまで現在のスレッドがブロックされます.
同期されたdispatch_group_waitを使用しているため、現在のスレッドがブロックされます.dispatch_asyncを使用して、プライマリ・スレッドがブロックされないように、メソッド全体をバックグラウンド・キューに入れます.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            let group = dispatch_group_create(); //    dispatch_group
            //dispatch_group_enter      Dispatch Group       。      dispatch_group_enter   dispatch_group_leave     ,               。
            dispatch_group_enter(group)

            //.....
            print("ssss")

            dispatch_group_leave(group)

            dispatch_group_wait(group, DISPATCH_TIME_FOREVER); //    

            dispatch_async(dispatch_get_main_queue(), {
                //  UI
            })
        }

まずgroupを作成し、groupenterとleaveの間のコードを実行します.その後、dispatch_group_waitを再利用してスレッドをここでブロックして待機させます.最後にUIのリフレッシュまたはグループ結果の処理を行う部分
しかし,スレッドをブロックする方法はnameに友好的ではないように見える.スレッドをブロックしない2つ目の方法dispatch_group_notifyを見てみましょう
  let groupDown = dispatch_group_create()
        dispatch_group_enter(groupDown)

        //....

        dispatch_group_leave(groupDown)

        dispatch_group_notify(groupDown, dispatch_get_main_queue()) {
                //  
        }

dispatch_group_notifyは非同期で動作します.Dispatch Groupにタスクがない場合は、そのコードが実行されます.
もう一つの書き方があります
let group1 = dispatch_group_create()
        dispatch_group_async(group1, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            //       1
        }
        dispatch_group_async(group1, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            //       2
        }
        dispatch_group_notify(group1, dispatch_get_main_queue()) {
            //       。       UI      dispatch_get_global_queue
        }

一般的にはこう使います
2、dispatch_apply dispatch_applyはforループのように表現されるが、異なる反復を同時に実行することができる.この関数は同期されているので、普通のforループと同じように、すべての作業が完了した後に戻るだけです.
閉包内で所定の数の作業の最適な反復数を計算する場合は、反復が多すぎて、反復ごとにわずかな作業しかないため、大量のオーバーヘッドが発生し、同時発生による収益を相殺することができるので注意する必要があります.スパンリング(striding)と呼ばれる技術は、反復ごとにいくつかの異なる仕事をすることによって、ここで役立ちます.同時のオーバーヘッドに注意してください.dispatch_applyはシリアル・キューには適していません.特に、タスクの進捗状況を追跡する必要がある場合は、コンカレント・サイクルに適しています.
使用するコードを見てみましょう
 dispatch_apply(3, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { (i:Int) -> Void in
                print(i)  //1,2,0                                         

        }