Observables in a remote interface are reactive streams of Event
instances in
Swift that, when connected to a Web Frame, can push data to the web
layer. They are implemented with
Combine Framework,
the reactive programming library that powers
SwiftUI, which means they are instances of
Publishers.
Examples
Observables can be declared any number of ways. The following examples are for a remote observable that sends events every time the network connection changes.
Declared as a @Published
property
Use the
@Published
attribute
to create an underlying publisher for the annotated property. Every time the
property is assigned a new value, the underlying publisher will emit the new
value to any subscribers.
The underlying publisher can be accessed with the $
operator ($connection
in
the following example).
class Network {
@Published var connection: Event?
}
Declared as a CurrentValueSubject
A
CurrentValueSubject
can be used to declare a publisher outside of a class.
let networkConnection = CurrentValueSubject<Event?, Never>(nil)
Web Frame Configuration
For the following example, we’ll be using an observable declared like the following:
let networkConnection = CurrentValueSubject<Event?, Never>(nil)
The observable reference can be passed directly to the Web Frame configuration.
Notice we must reset the type of the publisher to AnyPublisher
by using
.eraseToAnyPublisher()
to conform to the
RemoteObservable
type expected by
Peregrine. This is known as type erasure in Swift.
let configuration = WebFrame.Configuration(
baseURL: ...
functions: ...
observables: [
"networkConnection$": networkConnection.eraseToAnyPublisher()
]
)
Observables must end in a dollar sign ($
) to denote a reactive property, as
popularized by Cycle.js. This isn’t merely
convention—the dollar sign is how ProxyClient knows it’s an observable, not a
function.
Swift API
Event
Remote observables must emit Event
objects, which represent a single value
sent to the web layer.
Initializers
init?<T: Encodable>(_ json: T)
Create an Event
with any encodable object.
Structs (or classes) must implement the
Encodable
protocol
from Swift:
struct Connection: Encodable {
let type: String
}
Then, objects can be passed to this constructor directly:
let event = Event(Connection(type: "wifi"))
This initializer will return nil
if encoding fails (highly unlikely).
Not all Events must be wrapped in objects. In Swift, many data types implement the Encodable protocol: strings, booleans, ints, doubles, arrays, dictionaries, etc.