티스토리 뷰
Future는 Publisher 프로토콜 을 conform하고 있다.
Swift에서 asynchronous 프로그래밍을 위해 callback기반 completion handler를 사용했는데, (Rx안쓴다면)
이제 Future를 사용하면 된다..!
Future는 말그대로 아직 일어나지 않은 미래를 의미한다(??)
Future는 Output과 Error를 가지고 있고 (Publisher를 conform하니까 당연쓰)
final public class Future<Output, Failure> : Publisher where Failure : Error
Promise 클로져가 있는데,
Promise 클로져는 이렇게 생겼다.
[1] 기본 사용법
let future = Future<Int, Never> { promise in
promise(.success(1))
}
future.sink(receiveCompletion: { print($0) },
receiveValue: { print($0) })
// 출력
// 1
// finished
let future = Future<Int, Never> { promise in
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
promise(.success(1))
}
}
future.sink(receiveCompletion: { print($0) },
receiveValue: { print($0) })
print("end")
// 출력
// end
// 1
// finished
위의 두 예제를 통해 알 수 있듯이
Future는 one-shot이다. 즉 promise에게 value나 error를 한번 보내고 나면 바로 finished 된다.
value를 두번 보내는 예제를 보면 더 명확하다.
첫번째 value를 보낸 후, 스트림이 바로 끝나기때문에 두번째 value가 출력이 안되는 것을 볼 수 있다.
let future = Future<Int, Never> { promise in
promise(.success(1))
promise(.success(2))
}
future.sink(receiveCompletion: { print($0) },
receiveValue: { print($0) })
// 출력
// 1
// finished
[2] 실제 예제
APIService의 getUser라는 메소드가 이렇게 생겼는데,
// session이 valid한지 체크할때 쓸 API.
func getUser(with session: String, completion: @escaping (Result<Void, APIError>) -> ()) {
let url = ""
let headers: HTTPHeaders = ["Cookie": "SESSION=\(session)"]
AF.request(url, method: .get, parameters: [:], headers: headers).responseData { (response) in
let statusCode = response.response?.statusCode ?? 0
let code = Code(rawValue: statusCode) ?? .notDefined
switch response.result {
case .success:
if code == .ok {
completion(.success(()))
} else {
completion(.failure(APIError(code: code)))
}
case .failure:
completion(.failure(APIError(code: code)))
}
}
}
뷰모델에서 completion 쓰기 싫어서 이런식으로 썼다.
func isValidSession(_ session: String) -> AnyPublisher<Bool, Never> {
return Future<Bool, Never> { promise in
apiService.getUser(with: session) { result in
switch result {
case .success:
promise(.success(true))
case .failure:
promise(.success(false))
}
}
}.eraseToAnyPublisher()
}
func determineNeedLogin() {
isValidSession(session)
.sink { isValid in
self.needLogin = !isValid
}
.store(in: &cancellables)
}
물론 eraseToAnyPublisher 안해주고 그냥 이렇게 해도 된다 (차이는 문서 참고!)
func isValidSession(_ session: String) -> Future<Bool, Never> {
return Future<Bool, Never> { promise in
apiService.getUser(with: session) { result in
switch result {
case .success:
promise(.success(true))
case .failure:
promise(.success(false))
}
}
}
}
[3] RxSwift의 어떤 개념과 대응될까?
RxSwift의 Observable.create 또는 Single과 비슷하다고 할 수 있겠다.
대응이 아니라 비슷하다고 말한 이유는
RxSwift의 Single은 success, error 두가지 이벤트만 받을 수 있는데, Future는 종료 이벤트까지 받을 수 있어서 Single과 대응된다고 하기가 좀 그렇고,,,
RxSwift의 Observable.create는 onCompleted를 해줘야지 스트림이 끝나는데, Future는 value나 error 한번 발행되면 알아서 스트림이 끝나니까 Observable.create 와 대응된다고 하기가 좀 그렇다,,
[ Reference ]
기본 사용법 예제들은 다 여기서 코드를 가져왔습니다.
[ 더 보면 좋을 것 ]
Future 의 value 프로퍼티를 통해 async/await syntax 를 사용할 수 도 있습니다.
func generateAsyncRandomNumberFromFuture() -> Future <Int, Never> {
return Future() { promise in
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
let number = Int.random(in: 1...10)
promise(Result.success(number))
}
}
}
let number = await generateAsyncRandomNumberFromFuture().value
print("Got random number \(number).")
자세한 것은 문서 > Integrating with Swift Concurrency 참고!
'🍏 > SwiftUI + Combine' 카테고리의 다른 글
[SwiftUI] Button의 Tappable 영역 (1) | 2020.09.06 |
---|---|
[SwiftUI] modifier의 순서를 고려하자 (특히 frame) (0) | 2020.09.06 |
[SwiftUI] 뷰의 이니셜라이저에서 @State, @Binding, @EnvironmentObject에 접근하기 (1) | 2020.08.31 |
[SwiftUI] Multi-platform App 만들기 - 프로젝트 세팅 (2) | 2020.08.06 |
[SwiftUI] ZStack 실전 예제들 (2) | 2020.05.16 |
- Total
- Today
- Yesterday
- cocoapod
- Flutter Spacer
- flutter 앱 출시
- Flutter Text Gradient
- ribs
- Flutter 로딩
- 플러터 얼럿
- SerializerMethodField
- Flutter Clipboard
- 장고 Custom Management Command
- Dart Factory
- drf custom error
- METAL
- Django Heroku Scheduler
- flutter deep link
- github actions
- Sketch 누끼
- ipad multitasking
- Watch App for iOS App vs Watch App
- Python Type Hint
- 플러터 싱글톤
- Django Firebase Cloud Messaging
- Django FCM
- 구글 Geocoding API
- flutter build mode
- Flutter getter setter
- 장고 URL querystring
- PencilKit
- DRF APIException
- flutter dynamic link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 |