TimerEngine

open class TimerEngine : Codable, Identifiable

This class implements the “executable heart” of the timer app.

BASIC OVERVIEW

This is a countdown timer, in seconds. It starts from a “starting” time, and counts down to 0, at which time it starts an alarm.

It is a class, as opposed to a struct, so it can be referenced, and so that it can be easily mutated.

The “granularity” of the timer is seconds. It does not deal with fractions of a second. Callbacks only happen on the second or state transitions, and can occur in any thread.

It has six “modes” of operation:

  • ### STOPPED MODE

The timer is “stopped.” It is set to the starting time, and the timer is not running.

  • ### COUNTDOWN MODE

This is the basic countdown mode, starting from the “starting time” threshold.

  • ### WARNING MODE

This is a threshold, in seconds. Once the coundown reaches this, the timer goes into “warning” mode. This cannot be less than the final threshold (or 0), and cannot be higher than the starting threshold.

  • ### FINAL MODE

This is a threshold, in seconds. Once the coundown reaches this, the timer goes into “final” mode. The timer is running. This cannot be less than 0, and cannot be higher than the warning threshold.

  • ### ALARM MODE

Once it hits 0, it goes into “alarm” mode. The timer stops running, once this threshold is encountered.

  • ### PAUSED MODE

The timer countdown is in one of the above ranges, but has been “paused.” It is not running.

Private API (Static Properties)

  • We will ask for a callback, every millisecond.

    Declaration

    Swift

    private static let _timerInterval: TimeInterval
  • The integer above our maximum number of hours.

    Declaration

    Swift

    static let maxHours: Int
  • The integer above our maximum number of minutes.

    Declaration

    Swift

    static let maxMinutes: Int
  • The integer above our maximum number of seconds.

    Declaration

    Swift

    static let maxSeconds: Int
  • The number of seconds in a minute.

    Declaration

    Swift

    static let secondsInMinute: Int
  • The number of seconds in an hour.

    Declaration

    Swift

    static let secondsInHour: Int

Private API (Instance Properties)

  • This is the actual timer instance that runs the clock.

    Declaration

    Swift

    private var _timer: RVS_BasicGCDTimer?
  • The time to be used as the starting point of the current countdown.

    It is adjusted, when pausing.

    Declaration

    Swift

    private var _startTime: Date?
  • This saves the last paused time.

    Declaration

    Swift

    private var _lastPausedTime: TimeInterval
  • This is used to determine whether or not to move to the next second.

    Declaration

    Swift

    private var _countdownTime: Int
  • This is the previous timer mode (to track transitions).

    Declaration

    Swift

    private var _lastMode: Mode

Public API (Typealias)

  • This is the structure of the callback for each “tick,” handed to the instance. It is called once a second. It may be called in any thread.

    Declaration

    Swift

    public typealias TimerTickHandler = (_ timerEngine: TimerEngine) -> Void

    Parameters

    timerEngine

    The timer engine instance calling it.

  • This is the structure of the callback for mode transitions, handed to the instance. It is called, once only, when the timer mode changes. It may be called in any thread.

    Declaration

    Swift

    public typealias TimerTransitionHandler = (_ timerEngine: TimerEngine, _ fromMode: Mode, _ toMode: Mode) -> Void

    Parameters

    timerEngine

    The timer engine instance calling it.

    fromMode

    The mode we have transitioned from.

    toMode

    The mode we have transitioned into.

Codable Coding Keys Enum

  • These are part of the Codable conformance. They are used to mark the various field in the encoder/decoder.

    See more

    Declaration

    Swift

    public enum CodingKeys : String, CodingKey

Timer Mode State Enum

  • This defines the six timer states

    See more

    Declaration

    Swift

    public indirect enum Mode : Equatable, CustomStringConvertible

Public API (Instance Properties)

  • id

    This is the unique ID of this instance.

    Declaration

    Swift

    public var id: UUID
  • This is any data that the implementor may want to attach to this instance.

    Declaration

    Swift

    public var refCon: Any?
  • This is the beginning (total) countdown time.

    Declaration

    Swift

    public var startingTimeInSeconds: Int
  • This is the threshold, at which the clock switches into “warning” mode.

    Declaration

    Swift

    public var warningTimeInSeconds: Int
  • This is the threshold, at which the clock switches into “final” mode.

    Declaration

    Swift

    public var finalTimeInSeconds: Int
  • The callback for the tick handler. This can be called in any thread.

    Declaration

    Swift

    public var tickHandler: TimerTickHandler?
  • The callback for the transition handler. This can be called in any thread. It may also be nil.

    Declaration

    Swift

    public var transitionHandler: TimerTransitionHandler?

Public API (Initializers)

  • Default initializer

    We specify all three thresholds. The starting threshold is required. The other two are optional, and will be ignored, if not specified.

    Declaration

    Swift

    public init(startingTimeInSeconds inStartingTimeInSeconds: Int = 0,
                warningTimeInSeconds inWarningTimeInSeconds: Int = 0,
                finalTimeInSeconds inFinalTimeInSeconds: Int = 0,
                transitionHandler inTransitionHandler: TimerTransitionHandler? = nil,
                id inID: UUID = UUID(),
                refCon inRefCon: Any? = nil,
                startImmediately inStartImmediately: Bool = false,
                tickHandler inTickHandler: TimerTickHandler? = nil
    )

    Parameters

    inStartingTimeInSeconds

    This is the beginning (total) countdown time. If not supplied, is set to 0.

    inWarningTimeInSeconds

    This is the threshold, at which the clock switches into “warning” mode. If not supplied, is set to 0.

    inFinalTimeInSeconds

    This is the threshold, at which the clock switches into “final” mode. If not supplied, is set to 0.

    inTransitionHandler

    The callback for each transition. This is optional.

    inID

    The ID of this instance (Standard UUID). It must be unique, in the scope of this app. A new UUID is assigned, if not provided.

    inRefCon

    Any data the implementer wants to attach to this instance. It is not saved or retrieved in the dictionary or encoder, nor is it affected.

    inStartImmediately

    If true (default is false), the timer will start as soon as the instance is initialized.

    inTickHandler

    The callback for each tick. This can be a tail completion, and is optional.

  • Codable Conformance. Decoder Initializer.

    Declaration

    Swift

    public required init(from inDecoder: any Decoder) throws

    Parameters

    inDecoder

    The decoder with the state.

Private API (Callbacks)

  • This is the “first-level” callback from the timer. It can be called in any thread.

    Declaration

    Swift

    func _timerCallback(_ inTimer: RVS_BasicGCDTimer, _ inSuccess: Bool)

    Parameters

    inTimer

    The timer object.

    inSuccess

    True, if the timer completed its term.

Public API (Computed Read/Write Properties)

  • This returns the entire timer state as a simple dictionary, suitable for use in plists. The instance can be saved or restored from this. Restoring stops the timer.

    Note

    This does not affect the tickHandler or transitionHandler properties.

    Declaration

    Swift

    var asDictionary: [String : any Hashable] { get set }
  • This is the current time. It can be set to change the time in the timer. The new value is clamped to the timer range.

    Declaration

    Swift

    var currentTime: Int { get set }
  • This returns the time, in a precise manner.

    You can also use this to set the timer to a specific time.

    Declaration

    Swift

    var currentPreciseTime: TimeInterval? { get set }

Public API (Computed Read-Only Properties)

  • This is the timer mode (computed from the timer state). Read-Only.

    Declaration

    Swift

    var mode: Mode { get }
  • This is a closed range, from one second after the warn or final (if no warn), or the very beginning (if no final), to (and including) the start time.

    Note

    The range needs to be at least one second long, to be valid.

    Declaration

    Swift

    var startRange: ClosedRange<Int> { get }
  • This is a closed range, from one second after the final, or the very beginning, to (and including) the warn time.

    Note

    If no warn time (set to 0), then this returns an empty range. The range needs to be at least one second long, to be valid.

    Declaration

    Swift

    var warnRange: ClosedRange<Int> { get }
  • This is a closed range, from the very beginning, to (and including) the final time.

    Note

    If no final time (set to 0), then this returns an empty range. The range needs to be at least one second long (value of 2), to be valid.

    Declaration

    Swift

    var finalRange: ClosedRange<Int> { get }
  • This is the entire timer range, expressed as a closed seconds range.

    Declaration

    Swift

    var fullRange: ClosedRange<Int> { get }
  • Returns true, if the timer is currently “ticking.”

    Declaration

    Swift

    var isTicking: Bool { get }
  • This returns an “optimized” string, with the current countdown time.

    Declaration

    Swift

    var timerDisplay: String { get }

Public API (Instance Methods)

  • This simply sets the last paused time, to the current time.

    Declaration

    Swift

    func resetLastPausedTime()
  • This forces the timer to sync directly to the given seconds. The date is the time that corresponds to the exact second. The timer is started, if it was not already running.

    Note

    This directly sets the timer to a running state, but the tickHandler and transitionHandler callbacks may not be immediately executed. The timer must already be in .countdown, .warning, or .final state.

    Declaration

    Swift

    func sync(to inSeconds: Int, date inDate: Date = .now)

    Parameters

    inSeconds

    The actual integer second.

    inDate

    The date that corresponds to the given second. If not supplied, .now is used.

  • Starts the timer from the beginning. It will do so, from any timer state.

    This will interrupt any current timer.

    Declaration

    Swift

    func start()
  • This stops the timer, and resets it to the starting point, with no alarm. It will do so, from any timer state.

    This will interrupt any current timer.

    Declaration

    Swift

    func stop()
  • This forces the timer into alarm mode. It will do so, from any timer state.

    This will interrupt any current timer.

    Declaration

    Swift

    func end()
  • This pauses a running timer. The timer must already be in .countdown, .warning, or .final state.

    Declaration

    Swift

    @discardableResult
    func pause() -> [String : any Hashable]

    Return Value

    The state of the instance, just prior to pausing (empty, if failed). Can be ignored.

  • This resumes a paused timer. The timer must already be in .paused state, or a new state should be provided.

    You can use this method to set a timer to a saved state, and start it going immediately.

    Note

    This does not affect the tickHandler or transitionHandler properties, unless they are provided as method arguments. If the tickHandler or transitionHandler method arguments are supplied, and the resume fails, they will not be applied.

    Declaration

    Swift

    @discardableResult
    func resume(_ inState: [String: any Hashable]? = nil,
                transitionHandler inTransitionHandler: TimerTransitionHandler? = nil,
                tickHandler inTickHandler: TimerTickHandler? = nil
                ) -> Bool

    Parameters

    inState

    The saved state of the timer. If provided, the timer is set to that state, and started immediately, as opposed to a regular resume.

    inTransitionHandler

    The callback for each transition. This is optional.

    inTickHandler

    The callback for each tick. This can be a tail completion, and is optional.

    Return Value

    True, if the resume was successful.

Public API (Codable Conformance)

  • Codable Conformance: The Encoder.

    Declaration

    Swift

    func encode(to inEncoder: any Encoder) throws

    Parameters

    inEncoder

    The Encoder to be loaded with our state.

Additional Accessors for the Timer Engine Class

  • Simple cast to the wrapper instance that “owns” this timer.

    Declaration

    Swift

    var timer: Timer? { get }
  • The group to which this timer’s container belongs.

    Declaration

    Swift

    var group: TimerGroup? { get }
  • The model that contains this timer.

    Declaration

    Swift

    var model: TimerModel? { get }