Targets · Swift · Drivers

Drivers

The native drivers that provide the interface, animation and network.

Contents

How a Program becomes Swift, in parts. Start with the introduction, then follow each part into the rendered output and the runtime it links against.

Defining a driver

A driver conforms to the Driver protocol, draining one context channel and reconciling the resources it owns. Here is a console driver: it drains the Console.Lines channel and prints each line that has changed since the last cycle.

final class ConsoleDriver: Driver {
    private var lastById: [Int: String] = [:]

    let channel = "Console.Lines"
    let kind: DriverKind = .array
    func start(_ addUpdates: @escaping AddUpdates) {}

    func dispatch(_ emissions: [Line]) {
        for line in emissions where lastById[line.id] != line.text {
            print(line.text)
            lastById[line.id] = line.text
        }
    }
}

Registering it

A program lists the drivers it uses; the runtime opens a channel for each and never hardcodes one.

Program.Application({ Main() }, [
    ConsoleDriver(),
])

How the runtime runs it

Each cycle the runtime opens the driver's channel, runs the reactive program (which emits into it), drains it, and hands the array to dispatch:

Context.openArray("Console.Lines")
program = Reactive.Run(program, updates)
driver.dispatch(Context.drainArray("Console.Lines"))

A driver that produces events — a timer, a network reply — calls the addUpdates it was given in start, which schedules the next cycle. The interface driver is the same shape, only its channel is the nested view tree and its dispatch reconciles SwiftUI views, registering custom components that return an AnyView:

struct MapView: UiComponent {
    let name = "Map.View"
    func render(_ attributes: Attributes, _ renderChildren: RenderChildren) -> AnyView {
        AnyView(MapKitView(/* … */))
    }
}