LoginSignup
4
4

AsyncStreamを触ってみた。

Last updated at Posted at 2024-03-02

AsyncStreamとは?

非同期のSequence, 要素が非同期的に流れてくる小川。 公式資料

従来はクロージャで実装していたものをSwift Concurrencyの記法、async awaitで書けるように変換できるのが嬉しい。(のだと思う…)

// 以下のように定義すると
var asyncStream: AsyncStream<String> {
    AsyncStream { continuation in
        Task {
            try? await Task.sleep(until: .now + .seconds(1))
            continuation.yield("🍑") // 川に桃を流す
            
            try? await Task.sleep(until: .now + .seconds(1))
            continuation.yield("🪑") // 川に椅子を流す
            
            try? await Task.sleep(until: .now + .seconds(1))
            continuation.yield("👢") // 川に長靴を流す
        }
    }
}

// 以下のように使用できる。
func startStreaming() {
    Task {
        for await sth in asyncStream {
            if sth == "🍑" {
                print("桃が流れてきました。")
            } else {
                print("ゴミが流れてきました。")
            }
        }
    }
}

実装例A

カメラのプレビュー用画像データを逐次流す

実装例B

タップされたらすぐに数字が増加する動機カウンターと、一カウントごとに1秒表示して数字が増加する非同期カウンターを実装する。

Simulator Screen Recording - iPhone 15 - 2024-03-02 at 13.33.23.gif

ContentView.swift
struct ContentView: View {
    @State private var model = Model()

    var body: some View {
        VStack {
            Text("Async: \(model.asyncCounter)")
            Text("Sync: \(model.syncCounter)")
            Button("Count Up") { model.countUp() }
        }
        .task { await model.startStreaming() }
    }
}
Model.swift
@Observable
final class Model {
    private(set) var syncCounter = 0
    private(set) var asyncCounter = 0
    private let delay: UInt64 = 1_000_000_000

    func countUp() {
        syncCounter += 1
        throwIntoStream?(syncCounter)
    }

    func startStreaming() async {
        for await value in counterValueStream {
            try? await Task.sleep(nanoseconds: delay)
            asyncCounter = value
        }
    }

    private var throwIntoStream:((Int)->Void)?
    private var counterValueStream: AsyncStream<Int> {
        AsyncStream { continuation in
            self.throwIntoStream = { value in
                continuation.yield(value)
            }
        }
    }
}

その他

WWDCの動画もあるらしい。(まだ見てない…。動画見るの面倒くさい…。)

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4