How to use Futures and Promises in Combine with SwiftUI | Advanced Learning #20
Combine
의 미래 값을 가지고 올 Publisher
인 Future
사용법을 통해 비동기 데이터를 처리Publisher
구독을 통한 Combine
프레임워크의 비동기 처리Future
구독을 통한 Combine
프레임워크의 비동기 처리 → Promise
값을 통한 completion
핸들러 func getFuturePublisher() -> Future<String, Error> {
return Future { promise in
self.getEscapingClosure { returnedValue, error in
if let error = error {
promise(.failure(error))
} else {
promise(.success(returnedValue))
}
}
}
}
class FuturesBootCampViewModel: ObservableObject {
@Published var title: String = "Starting Title"
var cancellables = Set<AnyCancellable>()
let url = URL(string: "https://www.google.com")!
init() {
// download()
// downloadWithEscapingClosure()
// downloadWithFuturePublisher()
downloadWithFuturePublisher2()
}
func download() {
getCombinePublisher()
.sink { _ in
} receiveValue: { [weak self] returnedValue in
self?.title = returnedValue
}
.store(in: &cancellables)
}
func downloadWithEscapingClosure() {
getEscapingClosure { [weak self] value, error in
self?.title = value
}
}
func downloadWithFuturePublisher() {
getFuturePublisher()
.sink { _ in
} receiveValue: { [weak self] returnedValue in
self?.title = returnedValue
}
.store(in: &cancellables)
}
func downloadWithFuturePublisher2() {
doSomethingInTheFuture()
.sink { _ in
} receiveValue: { [weak self] returnedValue in
self?.title = returnedValue
}
.store(in: &cancellables)
}
func getCombinePublisher() -> AnyPublisher<String, URLError> {
URLSession.shared.dataTaskPublisher(for: url)
.timeout(1, scheduler: DispatchQueue.main)
.map({ _ in
return "NEW VALUE"
})
.eraseToAnyPublisher()
}
func getEscapingClosure(completionHandler: @escaping (_ value: String, _ error: Error?) -> ()) {
URLSession.shared.dataTask(with: url) { (data, response, error) in
completionHandler("New Value2", nil)
}
.resume()
}
func getFuturePublisher() -> Future<String, Error> {
return Future { promise in
self.getEscapingClosure { returnedValue, error in
if let error = error {
promise(.failure(error))
} else {
promise(.success(returnedValue))
}
}
}
}
func doSomething(completionHandler: @escaping (_ value: String) -> ()) {
DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
completionHandler("NEW STRING")
}
}
func doSomethingInTheFuture() -> Future<String, Never> {
Future { promise in
self.doSomething { value in
promise(.success(value))
}
}
}
}
Future
은 Publish
타입 중 성공/실패가 확실하게 결과값이 나오는 '하나'의 값을 리턴promise
를 통해 값 리턴 → 이스케이핑 클로저에 리턴값 및 에러를 핸들링 → Future
를 구독하는 다운로드 코드에서 Combine
프레임워크의 sink
, store
사용struct FuturesBootCamp: View {
@StateObject private var viewModel = FuturesBootCampViewModel()
var body: some View {
Text(viewModel.title)
.font(.largeTitle)
.fontWeight(.semibold)
}
}