0
0
iOS Swiftmobile~20 mins

Async sequences in iOS Swift - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Async Numbers Stream
This screen shows numbers from 1 to 10 one by one with a 1-second delay using async sequences.
Target UI
-------------------------
| Async Numbers Stream  |
|-----------------------|
| Number:               |
|                       |
| [Start Stream]        |
-------------------------
Display a number starting from 1 to 10, updating every second.
Use Swift async sequences to generate the numbers asynchronously.
Show a button labeled 'Start Stream' that starts the async sequence when tapped.
Disable the button while the stream is running.
Update the displayed number on the screen as each number is received.
Starter Code
iOS Swift
import SwiftUI

struct AsyncNumbersStreamView: View {
    @State private var currentNumber: Int? = nil
    @State private var isStreaming = false

    var body: some View {
        VStack(spacing: 20) {
            Text("Number: \(currentNumber.map(String.init) ?? "")")
                .font(.largeTitle)
                .padding()

            Button("Start Stream") {
                // TODO: Start async sequence here
            }
            .disabled(isStreaming)
            .padding()
            .background(isStreaming ? Color.gray : Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
        }
        .padding()
    }
}

struct AsyncNumbersStreamView_Previews: PreviewProvider {
    static var previews: some View {
        AsyncNumbersStreamView()
    }
}
Task 1
Task 2
Task 3
Task 4
Solution
iOS Swift
import SwiftUI

struct AsyncNumbersStreamView: View {
    @State private var currentNumber: Int? = nil
    @State private var isStreaming = false

    var body: some View {
        VStack(spacing: 20) {
            Text("Number: \(currentNumber.map(String.init) ?? "")")
                .font(.largeTitle)
                .padding()

            Button("Start Stream") {
                Task {
                    await startNumberStream()
                }
            }
            .disabled(isStreaming)
            .padding()
            .background(isStreaming ? Color.gray : Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
        }
        .padding()
    }

    func numberAsyncSequence() -> AsyncStream<Int> {
        AsyncStream { continuation in
            Task {
                for number in 1...10 {
                    try? await Task.sleep(nanoseconds: 1_000_000_000) // 1 second
                    continuation.yield(number)
                }
                continuation.finish()
            }
        }
    }

    func startNumberStream() async {
        isStreaming = true
        for await number in numberAsyncSequence() {
            currentNumber = number
        }
        isStreaming = false
    }
}

struct AsyncNumbersStreamView_Previews: PreviewProvider {
    static var previews: some View {
        AsyncNumbersStreamView()
    }
}

This solution uses AsyncStream to create an asynchronous sequence that yields numbers from 1 to 10 with a 1-second delay between each.

The startNumberStream() function runs asynchronously and updates the currentNumber state as each number is received, which updates the UI.

The button triggers this async function inside a Task to run asynchronously without blocking the UI.

The button is disabled while streaming to prevent multiple streams running at once.

Final Result
Completed Screen
-------------------------
| Async Numbers Stream  |
|-----------------------|
| Number: 1             |
|                       |
| [Start Stream]        |
-------------------------

(After 1 second)
-------------------------
| Async Numbers Stream  |
|-----------------------|
| Number: 2             |
|                       |
| [Start Stream]        |
-------------------------

... continues until Number: 10
User taps 'Start Stream' button.
Button disables to gray color.
Number updates every second from 1 to 10.
After 10, button re-enables for another run.
Stretch Goal
Add a 'Stop Stream' button that appears while streaming to cancel the number sequence early.
💡 Hint
Use a Task handle to cancel the running async task and reset states.