項目種別
補足
登場した回
伝えた回
分類
記載日
Sep 28, 2022 6:58 AM
関連資料
Swift Concurrency の withCheckedContinuation
に @escaping
を付与していないクロージャーをクロージングオーバーできることが不思議に思えましたけれど、調べてみるとそこから Swift Concurrency の特徴が窺えてきました。
通常の Dispatch のような非同期処理の場合、クロージングオーバーされたクロージャーはスコープを超えて延命されるため @escaping
を付与して延命可能にする必要がありますが、Swift Concurrency の場合は await
で処理が中断されるため、延命しなくても通常の生存期間を超えて存在することはなくなり、そのため @escaping
ではなくてもエラーにならない様子でした。
エラーになる場面
例えば次のコードだと、引数として用意されたf
を、いつ呼ばれるかはスレッド次第な async
メソッドに渡すことですなわち f
が実行されるより前に関数を抜けることになるため、その生存範囲を超えて生存することになるため f
に @escaping
がないとエラーになります。
func a(f: () -> Void) async {
DispatchQueue.global().async {
f()
}
}
エラーにならない場面
対して Swift Concurrency の場合、引数として用意された f
がありますが、これを await
を付与した関数にクロージングオーバーして渡したとしても、並行処理な await
が付与された行はその処理が終わるまでここで中断されるため、元の関数 a
の終了まで辿り着くことはありません。そうすると f
は通常の生存期間内にあるため、それに @escaping
がついている必要はない様子です。
func a(f: () -> Void) async {
await myWithCheckedContinuation { continuation in
f()
continuation.resume()
}
}