티스토리 뷰
안녕하세요 :) Zedd입니다.
오늘은 AsyncSequence에 대해서 공부해보겠습니다.
# Sequence
AsyncSequence가 Sequence와 유사하기 때문에..
Swift ) Sequence도 한번 보고 오시면 좋을 것 같습니다 👀
# AsyncSequence
AsyncSequence는 Sequence와 유사하지만,
✔️ 한번에 하나씩 단계(step)별로 진행할 수 있는 값 목록을 제공 + 비동기성을 추가한 타입 ✔️ 입니다.
AsyncSequence역시 for-in loop에 사용할 수 있는데요.
for value in AsyncSequence타입 {}
자 생각해봅시다. AsyncSequence는 뭔가 비동기~~친구인데,
사용할 때 값이 전부 or 일부가 아직 없는 상태일 수도 있겠죠!!!!!!
그래서 AsyncSequence는
for await value in AsyncSequence타입 {}
await과 같이 사용하게 됩니다.
그러니까 AsyncSequence는 for-in loop가 아닌 for-await-in loop를 사용하는 것이죠 :D
또한, AsyncSequence가 throwable하다면, for-try-await-in loop를 사용해야합니다.
왜냐면, 일반 Sequence와 다르게 비동기적으로 요소를 가져오는데,
비동기적으로 가져온다는 것 == 실패할 가능성이 있다는 걸 의미합니다.
그래서 try와 같이 사용되는것이구요 ㅎㅎ
💡 참고로 실패하게 되면 for-loop문은 종료됩니다.
그러니까 AsyncSequence가 종료되려면
1. 완전히 끝나거나
2. error가 나거나
인거죠! 요건 아래에서 예제로 더 자세히 보도록 할게요 ㅎㅎ
# 예제
대표적인 AsyncSequence를 살펴보겠습니다.
let endpointURL = URL(string: "https://zeddios.tistory.com")!
do {
for try await line in endpointURL.lines {
print(line)
}
} catch {
}
/*
<!doctype html>
<html lang="ko">
<head>
....
....
...
</html>
*/
iOS 15에서, URL타입의 인스턴스 프로퍼티로 lines가 나왔습니다.
해당 URL의 리소스 데이터 (= text line)의 비동기 시퀀스입니다. 즉, AsyncSequence이죠.
(사실은 AsyncLineSequence인데, 일단 궁극적으로 AsyncSequence임)
이 lines는 throwable 하기 때문에 for-try-await-in loop를 사용한 것을 볼 수 있습니다.
또, RxSwift가 6.5.0버전에서 Swift Concurrency를 지원하게 되었는데요.
do {
for try await value in observable.values {
print("Got a value:", value)
}
} catch {
print("Got an error:", error)
}
요런것이 가능해졌죠!!!
🤓 : observable.values가 AsyncSequence구나..!
# AsyncSequence Operator
Sequence와 유사하다고 계속 말씀드렸죠!
Sequence에서 사용되는 다양한 Operator를 AsyncSequence에서도 동일하게 사용할 수 있습니다.
let endpointURL = URL(string: "https://zeddios.tistory.com")!
let lineCount = endpointURL.lines.map { $0.count } ✅
do {
for try await line in lineCount {
print(line)
}
} catch {
}
/*
15
16
6
...
*/
이런식으로 사용할 수 있게 되는거죠!
# Conforming to the AsyncSequence Protocol
요부분은 Swift ) Sequence를 읽고오시면 이해가 더 잘되실 듯 합니다.
Custom Sequence를 만들때와 거의 똑같은데,
✔️ AsyncSequence, AsyncIteratorProtocol을 준수해야한다는 것
✔️ next()와 makeAsyncIterator()를 둘 다 구현해야한다는 것. (Sequence때는 next()만 구현하면 됐었음..)
만 다릅니다.
struct Zedd: AsyncSequence, AsyncIteratorProtocol {
typealias Element = Int
var current = 1
mutating func next() async throws -> Element? {
defer { current += 1 }
return current
}
func makeAsyncIterator() -> Zedd {
self
}
}
이런식으로 해주면
let zedd = Zedd()
Task {
do {
for try await value in zedd {
if value > 10 { break }
print(value)
}
} catch {
}
}
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 10
요렇게 zedd를 AsyncSequence로 사용할 수 있습니다.
현재 Zedd내의 next()는
mutating func next() async ✅ throws ✅ -> Element? {
defer { current += 1 }
return current
}
throwable한 메소드인데요.
[Throw Error]
위에서 실패(Error)가 나면 for-in loop는 종료된다고 그랬죠?
에러를 진짜 내보겠습니다.
enum ZeddError: Error {
case someError
}
struct Zedd: AsyncSequence, AsyncIteratorProtocol {
typealias Element = Int
var current = 1
mutating func next() async throws -> Element? {
if current == 5 { throw ZeddError.someError } ✅
defer { current += 1 }
return current
}
func makeAsyncIterator() -> Zedd {
self
}
}
current가 5가 되면 에러를 던지게 해놨습니다.
결과는~~
let zedd = Zedd()
Task {
do {
for try await value in zedd {
if value > 10 { break }
print(value)
}
} catch {
print(error)
}
}
// 1
// 2
// 3
// 4
// someError ✅
에러가 방출되고 for-loop는 종료된 것을 볼 수 있습니다.
[throws 제거]
mutating func next() async ✅ throws ✅ -> Element? {
defer { current += 1 }
return current
}
이 throws를 뺄 수 있습니다. (컴파일 에러 안남)
그러면!!!
Task {
for await value in zedd {
if value > 10 { break }
print(value)
}
}
이렇게 do-catch문도, try문도 없는 for-await-in loop를 사용할 수 있게됩니다.
📝 AsyncSequence를 위처럼 만들수도 있지만, AsyncStream을 사용해서 AsyncSequence를 만들 수도 있습니다 👻
그건 다음 글에서!
➡️ AsyncStream / AsyncThrowingStream 읽으러 가기
참고 :
'Swift > Concurrency' 카테고리의 다른 글
Structured Concurrency / Unstructured Concurrency (0) | 2023.07.23 |
---|---|
AsyncStream / AsyncThrowingStream (feat. RxSwift + Concurrency) (0) | 2022.02.07 |
Combine → Swift Concurrency(async/await)로 바꾸기 (feat. 느낀점) (3) | 2022.01.25 |
Actor (4) - Sendable (3) | 2021.10.11 |
Swift ) Actor (3) - isolated parameter / nonisolated keyword (1) | 2021.08.29 |
- swift tutorial
- swift delegate
- 피아노
- WKWebView
- Xcode
- 스위프트
- swift3
- np-complete
- np-hard
- ios 13
- IOS
- 회고
- swift array
- Accessibility
- swift 공부
- Git
- fastlane
- WWDC
- Swift
- UIBezierPath
- actor
- WidgetKit
- SwiftUI
- FLUTTER
- 스위프트 문법
- iOS delegate
- 제이슨 파싱
- github
- Combine
- swift sort
- Total
- Today
- Yesterday