見出し画像

楽しい!Swift。 - A Swift Tour (Concurrency)

非同期処理する場合に使うことができる機能です。async を使うことで非同期に実行される関数を定義できます。

非同期に使いたい関数ににasync をつけます。

func fetchUserID(from server: String) async -> Int {
    if server == "primary" {
        return 97
    }
    return 501
}

func fetchUserID(from server: String) async -> Int

呼び出す時はawaitをつけます。

func fetchUsername(from server: String) async -> String {
    let userID = await fetchUserID(from: server)
    if userID == 501 {
        return "John Appleseed"
    }
    return "Guest"
}

let userID = await fetchUserID(from: server)

非同期関数の呼び出しに async let を使うことで、他の非同期関数と並列に実行することができます。戻り値を使う箇所には await を書きます。

func connectUser(to server: String) async {
    async let userID = fetchUserID(from: server)
    async let username = fetchUsername(from: server)
    let greeting = await "Hello \(username), user ID \(userID)"
    print(greeting)
}

async let userID = fetchUserID(from: server)
async let username = fetchUsername(from: server)

同期的なコードから非同期関数を呼び出す場合は Task を使います。Task は非同期関数の終了を待ちません。

Task {
    await connectUser(to: "primary")
}

"async let"で同時並行処理はできますが構造化するために、タスクグループ(task group)を作って使うことができます。連続処理が行うときに使えます。

let userIDs = await withTaskGroup(of: Int.self) { group in
    for server in ["primary", "secondary", "development"] {
        group.addTask {
            return await fetchUserID(from: server)
        }
    }


    var results: [Int] = []
    for await result in group {
        results.append(result)
    }
    return results
}


classと同じようにactorは宣言できます。
actorはデータ競合を防ぐ仕組みで異なる非同期関数が同時に同じactorで作られたインスタンスは一つの処理のみに限定され処理されます。

actor ServerConnection {
    var server: String = "primary"
    private var activeUsers: [Int] = []

    func connect() async -> Int {
        let userID = await fetchUserID(from: server)
        // ... communicate with server ...
        activeUsers.append(userID)
        return userID
    }
}

actorを使うためにはawait をつける必要があります。

let server = ServerConnection()
let userID = await server.connect()


参考サイト


この記事が気に入ったらサポートをしてみませんか?