일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- swift 5.9
- ios
- swift
- Tuist Swift
- swift 6
- Combine
- GCD
- observable
- swift database
- KeyPath
- swiftdata
- realm
- SwiftUI
- ios swiftdata
- ribs
- RxSwift
- 네트워크 통신
- Firebase
- Firebase Analytics
- Swift Tuist
- JSON
- xcode
- 카카오뱅크 ios
- SeSAC
- Tuist
- Subject
- arc
- ios database
- Subscribe
- swift db
- Today
- Total
천원의 개발
iOS Continuation 정리 본문
안녕하세요. 천원입니다.
오늘은 CompletionHandler로 값을 리턴하는 함수들을 async await 스타일로 변경할 때 사용하는 Continuation에 대하여 학습해 보겠습니다.
공식 문서를 보면 CheckedContiuation과 UnsafeContination 두 종류가 있는데 한번 확인해 보겠습니다.
동기와 비동기 코드의 사이를 인터페이스하는 메커니즘으로, 정확성 위반을 기록한다고 하네요.
이친구는 정확성을 검사하지 않는다고 하네요.
이제 코드를 보자면 dataTask함수의 completionHandler를 통해서 받은 data를 다시 handler에 실어서 보내주는 코드입니다.
func requestImage(handler: @escaping ((Data) -> Void)) {
let request = URLRequest(url: URL(string: url)!)
URLSession.shared.dataTask(with: request) { data, response, error in
handler(data!)
}.resume()
}
requestImage { data in
print(data)
}
이러한 코드를 async await 문법으로 변경해 볼텐데 아래와 같이 CheckedContinuation을 사용하는 함수 withCheckedContinuation과 withCheckedThrowingContinuation이 존재하는데 차이점을 보면 이름처럼 error를 throw 할때는 withCheckedThrowingContinuation를 사용하는 것 같네요.
먼저 withCheckedContinuation를 사용해 보겠습니다.
func requestImageAsycAwait() async -> Data {
let request = URLRequest(url: URL(string: url)!)
return await withCheckedContinuation { continuation in
URLSession.shared.dataTask(with: request) { data, response, error in
continuation.resume(returning: data!)
}.resume()
}
}
Task {
let data = await requestImageAsycAwait()
}
dataTask 함수를 withCheckedContinuation Handler 내부에 위치시켜 data를 resume 함수로 리턴하는 모습입니다.
continuation의 구체적인 타입을 확인해보면 Data와 Never를 제네릭으로 가지고 있는걸 보니 에러를 핸들링 하지 않기 때문에 Never가 들어간 모습입니다.
이번에는 withCheckedThrowingContinuation을 사용해 보면
func requestImageAsycAwait() async throws -> Data {
let request = URLRequest(url: URL(string: url)!)
return try await withCheckedThrowingContinuation { continuation in
URLSession.shared.dataTask(with: request) { data, response, error in
if let data {
continuation.resume(returning: data)
} else if let error {
continuation.resume(throwing: error)
}
}.resume()
}
}
Task {
do {
let data = try await requestImageAsycAwait()
} catch {
print(error)
}
}
더 안정적인 코드가 작성이 되었습니다.
다음으로 UnsafeContinuation을 간단하게 보자면 CheckedContiuation이랑 사용법은 완전히 동일하지만 Continuation을 사용할 때는 resume을 호출하지 않으면 코드가 영원히 await 상태에 머물게 되고 이는 리소스 낭비로 이어지게 되는데, CheckedContiuation을 사용하면 콘솔창에 명시적으로 leaked되고 있음을 알려주지만
UnsafeContinuation를 사용하게 되면 아무런 에러가 발생하지 않는 모습입니다. UnsafeContinuation는 오버헤드가 적은 반면에 사용 시에 주의가 필요하겠네요.
출처:
https://developer.apple.com/documentation/swift/checkedcontinuation
'iOS&Swift🍎 > iOS' 카테고리의 다른 글
iOS Background Tasks(백그라운드에서 API 호출하기) (0) | 2024.02.20 |
---|---|
iOS KeyPath 정리 (1) | 2023.12.26 |
iOS Tuist 적용하여 여러 프로젝트 관리하기 (0) | 2023.10.24 |
iOS Preview 보면서 codebase로 작업하기 (0) | 2023.07.12 |
iOS Realm 데이터베이스를 활용하여 위젯 만들기(Realm 파일 공유) (0) | 2023.01.02 |