Introduction to Combine in iOS

Introduction to Combine in iOS

What is Combine?

The Combine framework provides a declarative Swift API for processing values over time. These values can represent many kinds of asynchronous events. Combine declares publishers to expose values that can change over time, and subscribers to receive those values from the publishers.

Key concept

Publisher

Publisher is the center of the entire process, it delivers elements to one or more Subscriber instances

public protocol Publisher {

    associatedtype Output
    associatedtype Failure : Error

    func receive<S>(subscriber: S) where S : Subscriber, Self.Failure == S.Failure, Self.Output == S.Input
}

All the Publisher inherit this protocol. Publisher protocol has 2 types you have to provide:

  • Output: Type of data emitted

  • Failure: Type of data for error

1 publisher will emit one of the following three types of values:

  • value: is what we need, the data

  • error: subscribers will receive the error

  • complete: is the end of the life cycle of a publisher

Subscriber

Subscribers will receive values from Publisher, all subscribers must inherit the Subscriber protocol.

public protocol Subscriber {

    associatedtype Input
    associatedtype Failure : Error

    func receive(subscription: Subscription)

    func receive(_ input: Self.Input) -> Subscribers.Demand

    func receive(completion: Subscribers.Completion<Self.Failure>)
}
  • Input: Type of data provided

  • Failure: Type of data for error

3 important methods:

  • receive(subscription:) when receiving a subscription from Publisher

  • receive(input:) when receiving value from Publisher and we will adjust the request for further data through Demand.

  • receive( completion:) when receiving completion from Publisher.

There are some ways to init a subscriber such as sink, assign, …

Life Cycle

  1. Publisher Creation:

    • The lifecycle begins when you create a publisher. A publisher emits values over time, representing a data stream.

    • Publishers can be created from various sources (e.g., arrays, network requests, user interactions).

  2. Subscriber Subscription:

    • When you subscribe to a publisher, a subscription is established.

    • The subscriber (consumer) receives values emitted by the publisher.

    • The subscription manages the connection between the publisher and subscriber.

  3. Subscription Request:

    • The subscriber can request a specific number of values using the request(_:) method on the subscription.

    • The demand can be:

      • .none: No demand for values.

      • .unlimited: Wants all values.

      • .max(Int): Limits the number of items received.

  4. Value Emission:

    • As the publisher produces values (e.g., from an array or network response), it sends them to the subscriber.

    • The subscriber’s receive(_:) method is called for each emitted value.

  5. Completion or Error Handling:

    • Publishers can complete normally or encounter errors.

    • When the publisher completes, the subscriber’s receive(completion:) the method is called with a .finished completion.

    • If an error occurs, the subscriber receives a .failure(Error) completion.

  6. Subscriber Cancellation:

    • Subscribers can cancel their subscription at any time using the cancel() method.

    • Cancellation releases resources and stops further value emissions.

Example Usage:

import Combine

let numbers = [1, 2, 3, 4, 5]
let publisher = numbers.publisher

let subscriber = Subscribers.Sink<Int, Never> { value in
  print("Received value:", value)
}

let subscription = publisher.subscribe(subscriber)
subscription.request(.max(3)) // Request only 3 values
// Output:
Received value: 1
Received value: 2
Received value: 3

Operators

In-between Publisher and Subscriber, they transform/filter the published value into something desired by the subscriber

Operators forward errors, only change values. They also manage scheduling/time, thread/queue movement, and more


Thanks for Reading! ✌️

If you have any questions or corrections, please leave a comment below or contact me via my LinkedIn account Pham Trung Huy.

Happy coding 🍻