MobiusCore/Source/MobiusLogger.swift (50 lines of code) (raw):
// Copyright Spotify AB.
// SPDX-License-Identifier: Apache-2.0
import Foundation
/// Protocol for logging init and update calls.
public protocol MobiusLogger {
associatedtype Model
associatedtype Event
associatedtype Effect
/// Called right before the `Initiate` function is called.
///
/// This method is only called for `MobiusController`-managed loops.
///
/// This method mustn't block, as it'll hinder the loop from running. It will be called on the
/// same thread as the `Initiate` function.
///
/// - Parameter model: the model that will be passed to the initiate function
func willInitiate(model: Model)
/// Called right after the `Initiate` function is called.
///
/// This method is only called for `MobiusController`-managed loops.
///
/// This method mustn't block, as it'll hinder the loop from running. It will be called on the
/// same thread as the initiate function.
///
/// - Parameters:
/// - model: the model that was passed to the initiate function
/// - first: the resulting `First` instance
func didInitiate(model: Model, first: First<Model, Effect>)
/// Called right before the `Update` function is called.
///
/// This method mustn't block, as it'll hinder the loop from running. It will be called on the
/// same thread as the update function.
///
/// - Parameters:
/// - model: the model that will be passed to the update function
/// - event: the event that will be passed to the update function
func willUpdate(model: Model, event: Event)
/// Called right after the `Update` function is called.
///
/// This method mustn't block, as it'll hinder the loop from running. It will be called on the
/// same thread as the update function.
///
/// - Parameters:
/// - model: the model that was passed to update
/// - event: the event that was passed to update
/// - result: the `Next` that update returned
func didUpdate(model: Model, event: Event, next: Next<Model, Effect>)
}
public extension MobiusLogger {
func willInitiate(model: Model) {}
func didInitiate(model: Model, first: First<Model, Effect>) {}
func willUpdate(model: Model, event: Event) {}
func didUpdate(model: Model, event: Event, next: Next<Model, Effect>) {}
}
final class NoopLogger<Model, Event, Effect>: MobiusLogger {}
/// Type-erased wrapper for `MobiusLogger`s
public final class AnyMobiusLogger<Model, Event, Effect>: MobiusLogger {
private let willInitiateClosure: (Model) -> Void
private let didInitiateClosure: (Model, First<Model, Effect>) -> Void
private let willUpdateClosure: (Model, Event) -> Void
private let didUpdateClosure: (Model, Event, Next<Model, Effect>) -> Void
/// Creates a type-erased `MobiusLogger` that wraps the given instance.
public init<Logger: MobiusLogger>(
_ logger: Logger
) where Logger.Model == Model, Logger.Event == Event, Logger.Effect == Effect {
if let anyLogger = logger as? AnyMobiusLogger {
willInitiateClosure = anyLogger.willInitiateClosure
didInitiateClosure = anyLogger.didInitiateClosure
willUpdateClosure = anyLogger.willUpdateClosure
didUpdateClosure = anyLogger.didUpdateClosure
} else {
willInitiateClosure = logger.willInitiate
didInitiateClosure = logger.didInitiate
willUpdateClosure = logger.willUpdate
didUpdateClosure = logger.didUpdate
}
}
public func willInitiate(model: Model) {
willInitiateClosure(model)
}
public func didInitiate(model: Model, first: First<Model, Effect>) {
didInitiateClosure(model, first)
}
public func willUpdate(model: Model, event: Event) {
willUpdateClosure(model, event)
}
public func didUpdate(model: Model, event: Event, next: Next<Model, Effect>) {
didUpdateClosure(model, event, next)
}
}