본문 바로가기
iOS/Swift

Meet AsyncSequence

by 바등쪼 2023. 2. 11.
 
https://developer.apple.com/videos/play/wwdc2021/10058/

AsyncSequence 예시 코드


@main
struct QuakesTool {
    static func main() async throws {
        let endpointURL = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.csv")!

        // skip the header line and iterate each one 
        // to extract the magnitude, time, latitude and longitude
        for try await event in endpointURL.lines.dropFirst() {
            let values = event.split(separator: ",")
            let time = values[0]
            let latitude = values[1]
            let longitude = values[2]
            let magnitude = values[4]
            print("Magnitude \(magnitude) on \(time) at \(latitude) \(longitude)")
        }
    }
}

 

Iterating Sequence


for quake in quakes {
    if quake.magnitude > 3 {
        displaySignificantEarthquake(quake)
    }
}
  • 우리가 흔하게 작성하는 sequence의 예시
AsyncSequence
1. async가 아닌 sequence와 유사하다.
2. throw 가능
3. 작업을 끝까지 완료하거나 오류로 종료 가능
4. map, allSatisfy등 다양한 오퍼레이터 사용 가능

How the compiler handles iteration


var iterator = quakes.makeIterator()
while let quake = iterator.next() {
    if quake.magnitude > 3 {
        displaySignificantEarthquake(quake)
    }
}
  • 컴파일러가 앞선 예시의 반복문을 처리하는 방식은 위와 같다.

 

Iterating an asyncSequence


for await quake in quakes {
    if quake.magnitude > 3 {
        displaySignificantEarthquake(quake)
    }
}
  • asyncSequence에서 반복문을 작성하는 방법은 위와 같다.
  • break, continue 구문도 사용 가능
  • throw도 가능하다.
    do {
        for try await quake in quakeDownload {
            ...
        }
    } catch {
        ...
    }

 

How the compiler handles asynchronous iteration


var iterator = quakes.makeAsyncIterator()
while let quake = await iterator.next() {
    if quake.magnitude > 3 {
        displaySignificantEarthquake(quake)
    }
}
  • 컴파일러가 asyncSequence를 처리하는 방식

 

Concurrently iterating inside an async task


let iteration1 = Task {
    for await quake in quakes {
        ...
    }
}

let iteration2 = Task {
    do {
        for try await quake in quakeDownload {
            ...
        }
    } catch {
        ...
    }
}

//... later on  
iteration1.cancel()
iteration2.cancel()
  • Task 블록 안에 반복문을 넣어 동시성을 추가 할 수 있다.
  • cancel()을 통해 최소도 가능하다.

 

 

Reading bytes from a URLSession


let (bytes, response) = try await URLSession.shared.bytes(from: url)

guard let httpResponse = response as? HTTPURLResponse,
      httpResponse.statusCode == 200 /* OK */
else {
    throw MyNetworkingError.invalidServerResponse
}

for try await byte in bytes {
    ...
}

 

Notifications


let center = NotificationCenter.default
let notification = await center.notifications(named: .NSPersistentStoreRemoteChange).first {
    $0.userInfo[NSStoreUUIDKey] == storeUUID
}

 

Using an AsyncStream


class QuakeMonitor {
    var quakeHandler: (Quake) -> Void
    func startMonitoring()
    func stopMonitoring()
}

let quakes = AsyncStream(Quake.self) { continuation in
    let monitor = QuakeMonitor()
    monitor.quakeHandler = { quake in
        continuation.yield(quake)
    }
    continuation.onTermination = { @Sendable _ in
        monitor.stopMonitoring()
    }
    monitor.startMonitoring()
}

let significantQuakes = quakes.filter { quake in
    quake.magnitude > 3
}

for await quake in significantQuakes {
    ...
}

 


Uploaded by

N2T

 

 

'iOS > Swift' 카테고리의 다른 글

Understanding Swift Performance  (2) 2023.03.13
Explore structured concurrency in Swift  (0) 2023.02.11
Use async/await with URLSession  (0) 2023.02.11
Meet async/await in Swift  (0) 2023.02.11
Opaque Type  (0) 2023.02.11

댓글