Skip to main content

observable

Macro observable 

Source
macro_rules! observable {
    ($(
        $(#[$meta:meta])*
        $vis:vis $name:ident {
            $(
                $(#[$field_meta:meta])*
                $field:ident : $ty:ty = $default:expr
            ),* $(,)?
        }
    )*) => { ... };
}
Expand description

Declare an @Observable model — the properties, not the plumbing.

@Observable class Model { var count = 0; var name = "Ada" } in Swift. Here it is a type whose fields are the properties, so the names are checked and the types come from the declaration:

observable! {
    /// Everything the app's windows share.
    pub AppModel {
        count: i64 = 0,
        name: String = "Ada",
    }
}

let model = AppModel::new();
model.count.set(model.count.peek() + 1);
assert_eq!(model.count.peek(), 1);
assert_eq!(model.name.peek(), "Ada");

Each field is a Property, with its own key path, so a view body that read count is rebuilt when count changes and left alone when name does. shared is the form an app usually wants — one model for the process, reachable from every window:

app::run(|| {
    let model = AppModel::shared();
    text(&format!("{}", model.count.get())).environment_model(model.as_model())
});

Reading through get inside a body is what subscribes it; peek reads without subscribing, for assertions that must not.