SwiftUIでいこう! -Async/Await(new!)
まずは説明がある公式サイト
いろんな使い方を説明してあるサイトです。
英語サイトはちょっとわかりにくいので
日本語でわかりやすく説明されているサイト、動画です。
同期、非同期を考えながらわかりやすく説明されているサイト。すごくわかりやすくて良いです。XcodeのPayground で紹介されているのも実行しやすくて大変参考になります。
XcodeのPlaygroundで実行していきます。まず非同期からおさらい。(iPad,MacのSwiftPlaygroundでは実行できないようです。)
非同期処理のコード。
import Foundation
let keyword = "カレー味"
let keyword_encode = keyword.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
// リクエストURLの組み立て
let req_url = URL(string: "https://sysbird.jp/toriko/api/?apikey=guest&format=json&keyword=\(keyword_encode!)&max=10&order=r")!
print("1.データの取得を開始します")
// リクエストするタスクを作成
let task = URLSession.shared.dataTask(with: req_url) { data, response, error in
print("2.データが取得できた")
}
// タスクの実行
task.resume()
print("3.すべての処理が終了")
このコードを実行すると上から順番に処理されません。
ほんとは最後に処理してほしい"3.すべての処理が終了"が最後に処理されず2番目に処理され、最後に処理してほしい"2.データが取得できた"が最後に処理されています。
"順番に処理されない"のが非同期処理というものです。処理に時間がかかるものなどは並列に処理できるのでよく使われています。
ここでの問題は、並行処理なので、片方の処理が失敗していてももう一つの処理が実行されてしまうので無駄も発生する場合があるということが挙げられます。
例えばよく使われるAPIを取得して処理を進めるという場合であれば、API取得失敗していても、次の処理が動いてしまうことなどがあります。
そこで最初の処理を確実に実行されたのを待ってから次の処理を実行させたい場合に便利に使えるようになったのが、今回のasync/awaitということになります。
非同期処理だけど、同期的に使うことができる。というのが少しややこしいところかなと思います。
"await"を使うと、
import SwiftUI
let req_url = URL(string: "https://www.apple.com/")!
Task {
print("1.データの取得を開始します")
let (_ , response) = try await URLSession.shared.data(from: req_url)
if (response as? HTTPURLResponse)?.statusCode == 200 {
print("2.データの取得できた")
}
print("3.すべての処理が終了")
}
順番通りに処理されたことがわかります。
asyncを使った方法です。asyncを使うことで関数が非同期関数であることを明示して使うことができます。
func getData() async throws {
print("1.データの取得を開始します")
let req_url = URL(string: "https://www.apple.com/")!
let (_ , response) = try await URLSession.shared.data(from: req_url)
if (response as? HTTPURLResponse)?.statusCode == 200 {
print("2.データの取得できた")
}
print("3.すべての処理が終了")
}
Task {
try await getData()
}
エラーのある可能性がある場合は
をつけないといけません。実行した結果。
と出力されます。