LoginSignup
16
17

More than 5 years have passed since last update.

main thread で動作させる話

Last updated at Posted at 2016-02-04

Main Thread で動作させたいコードなどが時々あります。 UITableViewreloadData() などは、場合によって、autolayout を background thread でやるなみたいなメッセージをもらったり、Core Data や OpenGL のように やっぱりちゃんと main thread で呼び出したい場合などが考えられます。

もっともオーソドックスなやり方は、以下のような書き方かもしれません。

dispatch_async(dispatch_get_main_queue()) { () -> Void in
    self.tableView.reloadData()
}

さてしかし、処理の順番などなんらかの都合で、dispatch_sync() を使いたい時は、こんなコードを書きたいと一瞬思うかもしれませんが、これを、main thread から呼び出してはいけません。

doStep1()  // 時間のかかる処理等
dispatch_sync(dispatch_get_main_queue()) { () -> Void in
    doStep2()  // step1 の結果を保存・表示する場合に main thread が必要な場合
}
doStep3()  // 後始末等

ならば、NSThread.isMainThread() で main thread かどうか、判定すればいいと思うかもしれませんが、同じコードを二回書かなくてはなりません。

if NSThread.isMainThread() {
    // your code
}
else {
    dispatch_sync(dispatch_get_main_queue()) { () -> Void in
        // your code
    }
}

で、技巧的に走って

let yourCode: () -> Void = {
    // your code
}

if NSThread.isMainThread() {
    yourCode()
}
else {
    dispatch_sync(dispatch_get_main_queue()) { () -> Void in
        yourCode()
    }
}

と書くこともできますが、似たような処理の都度何度もこんな書き方をするのは面倒で、なおかつ可読性が落ちます。そこで、より使いかってを考えれば、そもそも引数としてコードを渡せるので、同期用と非同期用の二種類の関数を用意すれば便利になりそうです。

dispatch_sync_main.swift
func dispatch_sync_main(block: () -> Void) {
    if NSThread.isMainThread() {
        block()
    }
    else {
        dispatch_sync(dispatch_get_main_queue()) { () -> Void in
            block()
        }
    }
}
dispatch_async_main.swift
func dispatch_async_main(block: () -> Void) {
    dispatch_async(dispatch_get_main_queue()) { () -> Void in
        block()
    }
}

こんな感じで、使いかってがよくなると思います。

    doStep1()
    dispatch_sync_main() {
        doStep2()
    }
    doStep3()
    dispatch_async_main() {
        self.tableView.reloadData()
    }

ネーミングが本物のGCDとまぎわらしいと思う場合は、_ をつけるなり、他の名前をつけるなり工夫しましょう。

16
17
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
16
17