LoginSignup
19
19

More than 5 years have passed since last update.

GCD(Grand Central Dispatch)でキューの順番とスピードを制御する方法(2/2)

Last updated at Posted at 2017-07-11

-> 前回からの続き

5. .concurrent属性 / .initiallyinactive属性

DispatchQueueはlabelとqosの他にattributesという属性をつけることができる。
.concurrent.initiallyinactiveの二つがあり、どちらもキューではなくWork Itemを制御するものです。

A .concurrent

同じ同じキューの中で、Work Itemを同時処理させる属性。(結果は下A図)

    let anotherQueue = DispatchQueue(label: "com.ayakosayama.anotherQueue", qos: .utility, attributes: .concurrent)

     func attribuesTest(){

        anotherQueue.async {
            for i in 0..<10{
                print("🔵",i)
            }
        }

        anotherQueue.async {
            for i in 100..<110{
                print("🔴",i)
            }
        }

        anotherQueue.async {
            for i in 1000..<1010{
                print("⚫️",i)
            }
        }
    }

B .initiallyInactive

WorkItemをキューの中で待機させておく。実行処理を別で書かないと発動しない。(結果は下B図)

    var inactiveQueue: DispatchQueue!
    let anotherQueue = DispatchQueue(label: "com.appcoda.anotherQueue", qos: .utility, attributes: .initiallyInactive)

    func attribuesTest(){

        inactiveQueue = anotherQueue

        anotherQueue.async {
            for i in 0..<10{
                print("🔵",i)
            }
        }

        anotherQueue.async {
            for i in 100..<110{
                print("🔴",i)
            }
        }

        anotherQueue.async {
            for i in 1000..<1010{
                print("⚫️",i)
            }
        }
    }

実行メソッド

        attribuesTest()
        if let queue = inactiveQueue{
            queue.activate()
        }

Screen Shot 2017-07-11 at 3.14.32 PM.png

6. global()でフリーなキューをランダムで選ぶ

これまでは自分でカスタムキューを作ってきましたが、システムがバックグラウンドで作ったdispatch queueのコレクション、つまりグローバルキュー(global queues)を使うこともできる。

    func globalQueue(){
        let globalQueue = DispatchQueue.global()

        globalQueue.async {
            print(globalQueue.label)  // com.apple.root.default-qos
            for i in 1..<1000{ print("⚫️",i)}
        }
    }

この場合は処理が短い&使われてなかったので、デフォルトのQOSが選ばれている。

7. delayqueue.asyncaAfter()でキューの遅れる時間を制御する

以下のように、キューの処理を2秒遅らすというプログラムを書いて実行してみます。

    func queueWithDelay(){
        print(Date())

        let delayqueue = DispatchQueue(label: "com.ayakosayama.delayqueue", qos: .userInteractive)

        let additinalTime:DispatchTimeInterval = .seconds(2)
        delayqueue.asyncAfter(deadline: .now() + additinalTime){
            print(Date())
        }
    }

結果:ちょうど2秒遅れてprint(Date)されている!

2017-07-11 21:14:13 +0000
2017-07-11 21:14:15 +0000

8. コールバック関数で、ダウンロード後UIに画像を描画する

    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var label: UILabel!

    func fetchImage(){
        label.text = "downloading..."
        let imageURL: URL = URL(string: "https://worldstrides.com/wp-content/uploads/2015/07/12-Chureito-pagoda-and-Mount-Fuji-Japan.jpg")!

        (URLSession(configuration: URLSessionConfiguration.default)).dataTask(with: imageURL, completionHandler: { (imageData, response, error) in

            if let data = imageData {

                DispatchQueue.main.async {
                    self.label.text = "finished downloading!"
                    self.imageView.image = UIImage(data: data)
                }
            }
        }).resume()
    }

imageViewに画像を表示させたい!という処理ですが、
UIに表示させるコマンド(imageview.image = UIImage(data:data))が画像ダウンロード前に実行されると、ダウンロードが終わっても表示されない!

そこで上記のように、

DispatchQueue.main.async {}で覆ってあげるとよい。

downloading.gif

おしまい!

元ネタこちら
Gihtubコードはこちら

19
19
2

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
19
19