Skip to content

Configuring a MobiusLoop

Jens Ayton edited this page May 27, 2020 · 8 revisions

So far, we’ve started the loop in the following manner:

let loop = Mobius.loop(update: update, effectHandler: effectHandler)
    .start(from: 2)

This means providing only the mandatory parameters (an Update function and an Effect handler) of a MobiusLoop, and using default values for the rest. This section describes what the optional parameters are and how to configure them.

Previously, we’ve immediately started the loop by the call to start(from: ...). If we don’t call it, we instead get a Mobius.Builder:

let loopBuilder: Mobius.Builder<MyModel, MyEvent, MyEffect> =
    Mobius.loop(update: update, effectHandler: effectHandler)

Here’s what you can configure in Mobius.Builder – details of each item are described below:

let loop = Mobius.loop(update: update, effectHandler: effectHandler)
    .withEventSource(eventSource)
    .withLogger(SimpleLogger(tag: "my loop")) // SimpleLogger can be found in MobiusExtras
    .withEventConsumerTransformer { $0 }
    .start(from: model)

withEventSource

The EventSource of your program is supposed to be used for external events (see Events in depth for more details). If you have multiple external event sources, they must be merged into a single EventSource before being hooked into Mobius (for example, using CompositeEventSourceBuilder).

Consider an event source as an effect handler without incoming effect objects and that just emits events on its own. Basically an event source lets the loop listen to external signals, for example network connectivity changes or timer ticks. UI events should not be sent to the loop via the event source, but instead from the outside of the loop through MobiusLoop.dispatchEvent(). It is possible to send UI events through an event source, and once an event reaches the update function there is no difference between the origins of the events. However avoid sending UI events through the event source, as it is intended for external events only.

You must be careful if you implement the EventSource interface directly. It has the same requirements as effect handlers, that is, it must release resources and stop emitting events when it is disposed.

withLogger

The MobiusLogger protocol enables you to inspect what the update function is doing (and the initiate function, when using MobiusController). Every event, effect, and model change in the loop will go through the logger, so if there are any issues with your loop, the logs tells you what state the loop was in when the problem happened, and how it got there. Because of the usefulness of loggers, we recommended that you always set one in debug builds. The MobiusExtras package contains a readymade logger called SimpleLogger.

withEventConsumerTransformer

This is an advanced feature which lets you intercept events sent to the loop and customize how they are dispatched. An event consumer transformer takes an event consumer ((Event) -> Void) and returns a new event consumer. The resulting modified consumer is used to channel all incoming events, regardless of whether they come from the effect handler, event source, or dispatchEvent method.

An example of where this is useful is MobiusController, which uses an event consumer transformer to dispatch all events to an internal background queue. While we don’t recommend implementing custom scheduling for Mobius loops, withEventConsumerTransformer is exposed to make it possible.