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.