Continuation
정의
멈췄다가 재개할 수 있는 객체
먼저 애플 공식문서를 살펴보면 동기코드와 비동기코드 사이의 인터페이스 역할을 하는 메커니즘이라고 설명이 되어있다.
즉 , 기존의 코드를 비동기적으로 사용하는데 도움을 주는 역할을 하는 것 같다.
그리고 빨간 영역이 아닌 것을 보면 correctness를 체크하는 것과 하지 않는 것으로 크게 나뉘는 것 같다.
⚠️ 주의
Continuation은 결국 resume이라는 메소드를 통해 인터페이스 역할을 하게되는데 이 resume 메소드는 항상
한번만 호출되야한다.
이때 resume메서드가 재대로 한번만 호출되었는지 ? 이런 다양한 오류 체크 여부에 따라 종류가 나뉘게된다.
종류
1) CheckedContinuation
struct CheckedContinuation<T, E> where E : Error
- 런타임에 오류를 체크한다.
- 생성 메소드
// 에러 발생 가능성 x
withCheckedContinuation { <#CheckedContinuation<T, Never>#> in
<#code#>
}
// 에러 발생 가능성 o
withCheckedThrowingContinuation { <#CheckedContinuation<T, any Error>#> in
<#code#>
}
2) UnsafeContinuation
- 런타임에 오류를 체크하지 않는다.
- 오류를 체크하지 않아 퍼포먼스가 좋지만 오류 발생 시 앱이 강제 종료될 수 있다.
- 생성 메소드
// 에러 발생 가능성 x
withUnsafeContinuation { <#UnsafeContinuation<T, Never>#> in
<#code#>
}
// 에러 발생 가능성 o
withUnsafeThrowingContinuation { <#UnsafeContinuation<T, any Error>#> in
<#code#>
}
resume 메서드
총 4가지 메서드가 있다.
...Continuation { continuation in
continuation.resume() // void 리턴
continuation.resume(with: <#T##Result<(), Never>#>) // Result 타입으로
continuation.resume(throwing: <#T##Never#>) // 에러 리턴
continuation.resume(returning: returnValue) // 리턴 값
}
약간 rxswit의 single과 combine의 future 생성할 때 느낌이 든다.
예제 코드
enum TmpError: Error {
case invalidData
}
func fetchData(completion: @escaping (Data?) -> Void) {
let random = Int.random(in: 1...2)
if random == 1 {
completion(nil)
}
completion(Data())
return
}
func asyncFetchData() async throws -> Data {
let data = try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Data, Error>) in
fetchData { data in
guard let data = data else {
continuation.resume(throwing: TmpError.invalidData)
return
}
continuation.resume(returning: data)
}
}
return data
}
정리
기존의 탈출 메서드 형태를 continuation을 활용하여 wrapping하여 비동기 코드가 가능하도록 제공되는 인터페이스로
정리할 수 있을 것 같다.
비동기 코드로 전환한다는 것은 즉 , 비동기 context안에서 사용해야한다는 것이고 그것은 Task 또는 비동기 함수 내에서
사용해야할 것 같다.
출처
'iOS > Swift Concurrency' 카테고리의 다른 글
Task Cancellation (0) | 2024.10.27 |
---|---|
구조적 동시성 (1) (0) | 2024.10.26 |
async await (0) | 2024.10.24 |
swift concurrency 등장배경 (0) | 2024.10.24 |
Task (0) | 2024.10.23 |