Swift5.5から登場したConcurrencyで並列処理を実現してみました。
まずは下のように一定時間待ってからprintするメソッドを作ります。
functestFunction() async { try? await Task.sleep(nanoseconds:1_000_000_000) print(1) try? await Task.sleep(nanoseconds:2_000_000_000) print(2) }
上のメソッドを3つ平行に動かす方法は下の通りです。
async letf1: ()= testFunction() async letf2: ()= testFunction() async letf3: ()= testFunction() _ = await [f1, f2, f3]
実行すると下のように3つの処理が並行して動いているログが表示されます。
viewDidLoadのような通常のメソッドから非同期な処理を呼びたい場合、下のようにTaskを使います。
classViewController:UIViewController { overridefuncviewDidLoad() { super.viewDidLoad() print("viewDidLoad1") Task { async letf1: ()= testFunction() async letf2: ()= testFunction() async letf3: ()= testFunction() _ = await [f1, f2, f3] } print("viewDidLoad2") } }
実行すると下のようなログになります。
Task内の処理を待たずにviewDidLoad内の処理が最後まで動いている事が分かりました。
実行時のスレッドも確認してみました。
下のようなTask内の処理はメインスレッドになります。
Task { print(Thread.isMainThread) // → true async letf1: ()= testFunction() async letf2: ()= testFunction() async letf3: ()= testFunction() _ = await [f1, f2, f3] }
下のメインスレッドでしかできない操作(viewの背景色変更)を試した所、エラーなく動かす事ができました。
classViewController:UIViewController { overridefuncviewDidLoad() { super.viewDidLoad() Task { view.backgroundColor = .blue } } }
バックグラウンドで動かしたい場合、下のようにTask.detachedを使います。
Task.detached { print(Thread.isMainThread) // → false async letf1: ()=self.testFunction() async letf2: ()=self.testFunction() async letf3: ()=self.testFunction() _ = await [f1, f2, f3] }
ただ、その場合でも呼び出し先のメソッドはメインスレッドになるので注意が必要です。
functestFunction() async { print(Thread.isMainThread) // → true }
もし呼び出し先でもバックグラウンドにしたい場合、下のようにTask.detachedメソッドを使う必要があります。
functestFunction() async { await Task.detached { print(Thread.isMainThread) }.value }