Skip to content

Instantly share code, notes, and snippets.

@crisanvlad
Created September 18, 2025 17:07
Show Gist options
  • Select an option

  • Save crisanvlad/9770fafea4d6dc1eb651792b6d9c4064 to your computer and use it in GitHub Desktop.

Select an option

Save crisanvlad/9770fafea4d6dc1eb651792b6d9c4064 to your computer and use it in GitHub Desktop.
CombineLatest failures
//
// TestViewModel.swift
// TestCombine
//
// Created by Vlad Crisan on 18.09.2025.
//
import Combine
import Foundation
// MARK: - MyError
enum MyError: Error {
case whatever
case other(Error)
}
// MARK: - TestViewModel
final class TestViewModel: ObservableObject {
private var count = 0
private var subscription: AnyCancellable?
func start() {
let publisherA = makePublisherA()
.handleEvents { _ in
print("A received subscription")
} receiveOutput: { output in
print("A received output: \(output)")
} receiveCompletion: { completion in
print("A received completion: \(completion)")
} receiveCancel: {
print("A received cancel")
} receiveRequest: { _ in
print("A received request")
}
let publisherB = makePublisherB()
.handleEvents { _ in
print("B received subscription")
} receiveOutput: { output in
print("B received output: \(output)")
} receiveCompletion: { completion in
print("B received completion: \(completion)")
} receiveCancel: {
print("B received cancel")
} receiveRequest: { _ in
print("B received request")
}
subscription = Publishers.CombineLatest(publisherA, publisherB)
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("Finished completion")
case .failure(let failure):
print("Failure :\(failure)")
}
}, receiveValue: { string, integer in
print("Result \(string), \(integer)")
})
}
func cancel() {
subscription?.cancel()
start()
}
func increment() {
count += 1
}
func makePublisherA() -> AnyPublisher<String, MyError> {
if count.isMultiple(of: 2) {
Deferred {
Future { promise in
Task {
do {
let _ = try await Task.sleep(nanoseconds: 2_000_000_000)
promise(.success("Success"))
} catch {
promise(.failure(.other(error)))
}
}
}
.eraseToAnyPublisher()
}
.eraseToAnyPublisher()
} else {
makeFailedPublisher1()
// makeFailedPublisher2()
}
}
private func makeFailedPublisher1() -> AnyPublisher<String, MyError> {
Fail(outputType: String.self, failure: MyError.whatever).eraseToAnyPublisher()
}
private func makeFailedPublisher2() -> AnyPublisher<String, MyError> {
Deferred {
Future { promise in
Task {
do {
let _ = try await Task.sleep(nanoseconds: 2_000_000_000)
promise(.failure(.whatever))
} catch {
promise(.failure(.other(error)))
}
}
}
.eraseToAnyPublisher()
}
.eraseToAnyPublisher()
}
func makePublisherB() -> AnyPublisher<Int, MyError> {
Deferred {
Future { promise in
Task {
do {
let _ = try await Task.sleep(nanoseconds: 4_000_000_000)
promise(.success(999))
} catch {
promise(.failure(.other(error)))
}
}
}
.eraseToAnyPublisher()
}
.eraseToAnyPublisher()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment