Skip to content

Combining Multiple Publishers (Swift)

A SwiftUI guide for coding agents. Also covers zip publishers, combinelatest form validation, mergemany cache and network, parallel requests combine, wait for two publishers.

Three Combine operators run publishers in parallel and gather the results, and the choice between them is about timing: Zip waits for all, CombineLatest re-emits on any change, Merge interleaves same-typed streams.

Zip: Wait for Every Publisher

Zip emits a tuple only when each publisher has produced a value, right for loading two requests that must land together, like product details plus related products.

cancellable = Publishers.Zip(
  service.fetch(product),
  service.fetchRelatedProducts(for: product)
)
.sink(
  receiveCompletion: { print($0) },
  receiveValue: { [weak self] product, related in
    self?.product = product
    self?.related = related
  }
)

CombineLatest: React to Any Change

Zip pairs values one to one, so it stalls when one input changes more often. CombineLatest emits the latest values whenever any input changes, once each has emitted at least once. That makes it the form-validation operator.

var isValid: AnyPublisher<Bool, Never> {
  Publishers
    .CombineLatest3($email, $password1, $password2)
    .allSatisfy { email, password1, password2 in
      email.contains("@") &&
        password1.count > 7 &&
        password1 == password2
    }
    .eraseToAnyPublisher()
}

Merge: One Pipe, Same Output Type

Merge and MergeMany interleave publishers of the same output type into one stream. The classic use is cache then network: the cached list renders first and the fresh response replaces it through the same assignment.

Publishers.MergeMany(
  service.fetchCachedFavorites(),
  service.fetchFavorites()
)
.replaceError(with: [])
.assign(to: &$products)

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-combining-multiple-combine-publishers-in-swift" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems