あなたはエラーを投げることはできませんが、エラーを返すことができます。
まず、あなたが同様にあなたの呼び出し関数を非同期に行う必要があります。
func execute(argument: someArg, completion: @escaping (Value?, Error?)->()) {
queue.async {
do {
// compute value here:
...
completion(value, nil)
} catch {
completion(nil, error)
}
}
}
完了ハンドラは、どの我々は可能性パラメータを取りたとえば、値またはエラーのいずれかを含む「結果」があります。ここでは、タプル(Value?, Error?)
があります。ここで、Value
はタスクによって計算されるタイプです。しかし、代わりに、これにはより便利なSwift Enumを活用することができます。 Result<T>
またはTry<T>
(ウェブを検索したい場合があります)。次のように
はその後、あなたはそれを使用します。
execute(argument: "Some string") { value, error in
guard error == nil else {
// handle error case
}
guard let value = value else {
fatalError("value is nil") // should never happen!
}
// do something with the value
...
}
役立つかもしれないいくつかのルール:
を関数は、内部で非同期関数を呼び出す場合、それは避けられないとしても、非同期関数となります。 *)
非同期関数には完了ハンドラが必要です(それ以外の場合は、「火災と忘れ」のようなものです)。
何があっても、完了ハンドラを呼び出す必要があります。
完了ハンドラが(呼び出し側に関して)非同期的に呼び出さなければなりません
機能を実行するために指定するパラメータを持っていない限り、完了ハンドラはプライベート実行コンテキスト(別名ディスパッチキュー)に呼び出されなければなりません完了ハンドラメインスレッドまたはメインディスパッチキューを使用しないでください。明示的にその事実をドキュメントに記述するか、意図的にデッドロックを危険にさらしたくない場合を除きます。
*)あなたは、呼び出し元のスレッドをブロックセマフォを使用してそれを同期させるためにそれを強制することができます。しかし、これは非効率的で、実際にはほとんど必要ありません。
これは多少面倒なようです。幸いにも、助けがあります - Future
またはPromise
を探して、これをきちんとラップして、コードをより簡潔かつ分かりやすくすることができます。
注:ユニットテストでは、非同期呼び出し(XCTestフレームワークを参照)を処理するための期待を使用します。