Declaring resources

Resources can be bundled with a Swift package and then be accessed in your code.

We can distinguish two types of resources : common resources (e.g interface builder files, core data files, asset catalogs, lproj folders..) and custom resources (e.g .json files, .txt files, .md files..):

Adding the former is pretty straightforward as Xcode automatically treats them as resources. No changes need to be made to the package manifest.

Simply drag them under `Sources/MyLibrary`, consider using a subfolder for resources to distinguish them from source files.

Custom resources however must be explicitly declared in the package manifest.

targets: […

`collect()` is a powerful operator that enables us to receive all at once the outputs from a publisher.

It collects all received elements, and emits a single array of the collection when the upstream publisher finishes.

[0, 1, 2, 3].publisher
.sink { (output) in
print(output)
}.store(in: &subscriptions)

The publisher will emit the values as they come — e.g starting with 0 and ending with 3 —

// 0
// 1
// 2
// 3

Using `collect()`, the publisher will hold the values and emit all of them once a `finished` event is sent — e.g …


SwiftUI enables us to access common pieces of information throughout the app using `@Environment` objects avoiding the cumbersomeness of passing data through the views.

There are many built-in environments such as `openURL`, `colorScheme` or `managedObjectContext` to manage data storage with Core Data.

All these environments are defined in the Swift standard library as part of an extension of the `EnvironmentValues`:

extension EnvironmentValues {
public var managedObjectContext: NSManagedObjectContext
}

While these built-in objects are very convenient, SwiftUI gives us the ability to create tailor-made environments to meet our needs.

In this demo, we’ll be creating a tracking environment object to follow…


While creating a custom operator out of Combine’s built-in ones in the `Publisher` extension is a useful (and quick!) technique to harmonize some common reactive behaviors, it is sometimes necessary to provide with some more in-depth customization to achieve our goal.

Combine enables us to conform to the `Publisher`, `Subscription` and `Subscriber` protocols to create a tailored operator and gain control over our flow.

Our purpose is to create a single-valued publisher which will deliver one value and completes immediately, or fails.

— Part 1: Creating a custom Publisher

First, we need to extend the `Publishers` enum which is «…


Property wrappers are one of Swift’s major new features enabling us to attach some specific behavior each time a property gets accessed or mutated.

It comes in very handy when one needs to encapsulate some common logic such as the user defaults which are often read and written to throughout the app lifecycle.

If you’ve been playing with SwiftUI, you may have already encountered some of these wrappers: @EnvironmentObject , @ObservableObject, or @Published.

Declaring a property wrapper is pretty straightforward since it only requires us to implement a `wrappedValue` property.

Let’s build a property wrapper that encapsulates some reactive behavior…


While Combine provides with a `sink` method that conveniently « creates the subscriber and immediately requests an unlimited number of values, prior to returning the subscriber. », the framework also enables us to define our own subscriber by conforming to the `Subscriber` protocol.

— Use case

class CustomSubscriber: Subscriber {
typealias Input = Int
typealias Failure = Never
func receive(subscription: Subscription) {
subscription.request(.max(1))
}
func receive(_ input: Int) -> Subscribers.Demand {
print("Value:", input)
return .none
}
func receive(completion: Subscribers.Completion<Never>) {
print("Completion: \(completion)")
}
}

Since the `Subscriber` protocol has two associated types namely `Input` and `Failure`, we must specify the type of values…


Functions, in Swift, are first-class citizens that can be passed as arguments, stored in properties or returned from functions.

When dealing with Swift built-in functions such as `map` and `forEach`, one often ends up using the trailing closure syntax to provide with the required behavior.

let stackView = UIStackView()
let views = [UIView(), UIView(), UIView()]
views.forEach { view in
stackView.addArrangedSubview(view)
}

Or, using the $ syntax:

views.forEach {
stackView.addArrangedSubview($0)
}

While the above implementation is quite clear, let’s see how we can leverage the power of first-class functions and improve code readability.

— Functions

First, let’s take a closer look…


Combine is designed around structs — which are value types — ensuring that a copy is made by the system whenever a resource is stored in a property (or passed around in functions) so it can deliver values without side-effects.

extension Publishers {/// A publisher that publishes a given sequence of elements.
/// When the publisher exhausts the elements in the sequence, the next request causes the publisher to finish.
public struct Sequence<Elements, Failure> : Publisher where Elements : Sequence, Failure : Error { {…}
}
}

When creating multiple subscribers, a copy of the publisher will be created…


switchToLatest() is one of the most powerful operator in Combine as it enables to switch entire publisher subscriptions on the fly while canceling the pending publisher subscription, thus switching to the latest one.

Only publishers that emit publishers can use the `switchToLatest()` operator.

AnyPublisher<AnyPublisher<[Post], Never>, Never>

Every time a publisher receives a new `Publisher` as output, the previous subscriptions from that stream will automatically be cancelled.

The operator is highly useful when it comes to chaining operations with a network request.

— Use case

When the user taps a view, we want to trigger a network request that sends us…


While Combine doesn’t provide a built-in API to handle UIKit’s gestures yet, the Publisher and Subscription protocols give us the ability to create our own solution.

— Creating a custom publisher

First, let’s create a custom publisher by conforming to the Publisher protocol which is composed of two associated types namely Output and Failure.

`Output` represents the type of value the publisher will produce and `Failure` is the type of error it can throw.

struct GesturePublisher: Publisher {
typealias Output = GestureType
typealias Failure = Never
private let view: UIView
private let gestureType: GestureType
init(view: UIView, gestureType: GestureType) {
self.view = view
self.gestureType …

Jullian Mercier

Senior iOS engineer. jullianmercier.com. @jullian_mercier.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store