// // Observation.swift // LuminateCore // // Created by Brendan Szymanski on 6/15/26. // import Foundation // MARK: - ObservationRegistrar /// Manages observation notifications for `@Observable` classes. /// /// When a tracked property changes, ``didChange()`` triggers the global /// ``onChange`` handler, which should be wired to the view update system /// during app initialization. /// /// ## Wiring /// Connect the registrar to the view update system during app startup: /// ```swift /// ObservationRegistrar.onChange = { StateManager.updateViews() } /// ``` public class ObservationRegistrar { /// Global callback invoked when any tracked property changes. /// Set this during app startup to connect to the view update system. public static var onChange: (() -> Void)? public init() {} /// Notifies the system that a tracked property changed. /// Triggers the global ``onChange`` handler. public func didChange() { Self.onChange?() } } // MARK: - ObservableProtocol /// Conforming types get automatic property-mutation notifications via ``Observable``. /// /// All `@Observable` classes automatically conform to this protocol. /// The ``_$observationRegistrar`` property is added by the `@Observable` macro. public protocol ObservableProtocol: AnyObject { /// The observation registrar that tracks property mutations. var _$observationRegistrar: ObservationRegistrar { get } } // MARK: - @Observable Macro Declaration /// Registers a class for observable property mutation tracking. /// /// When a property of an observable class is mutated, the framework /// automatically triggers a view update. Use with ``@State`` in views: /// /// ```swift /// @Observable /// class PlayerViewModel { /// var title: String = "" /// var position: TimeInterval = 0 /// let id: UUID = .init() /// } /// /// struct PlayerView: View { /// @State private var model = PlayerViewModel() /// var view: Body { /// VStack { /// Text(model.title) /// Button("Seek") { model.position += 10 } /// } /// } /// } /// ``` /// /// The macro: /// - Adds an ``_$observationRegistrar`` stored property to the class /// - Adds a stored backing property ``_$`` for each tracked `var`, preserving /// its type and initial value /// - Converts each stored `var` property to a computed `get`/`set` pair that /// reads/writes the ``_$`` backing property and calls /// ``ObservationRegistrar/didChange()`` on every mutation /// /// Stored `let` properties and computed properties are left untouched. /// /// - Important: The registrar must be wired up before use: /// ```swift /// ObservationRegistrar.onChange = { StateManager.updateViews() } /// ``` @attached(member, names: named(_$observationRegistrar), arbitrary) @attached(memberAttribute) public macro Observable() = #externalMacro( module: "LuminateObservationMacros", type: "ObservableMacro" ) /// Internal macro used by ``Observable`` to add accessor observers to stored properties. /// /// This macro is applied automatically by `@Observable` to each stored `var` property. /// Do not use directly. @attached(accessor) public macro ObservationTracked() = #externalMacro( module: "LuminateObservationMacros", type: "ObservableMacro" )