Skip to content

Add @AppStorage#60

Merged
colemancda merged 5 commits into
masterfrom
feature/appstorage
Jul 24, 2026
Merged

Add @AppStorage#60
colemancda merged 5 commits into
masterfrom
feature/appstorage

Conversation

@colemancda

Copy link
Copy Markdown
Member

@AppStorage("key") for Bool, Int, Double, and String — values that outlive the process.

Keeping the core platform-free

Persistence needs a platform store, but the core owns no platform APIs. So the backing store is a protocol the host installs: an in-memory store by default (which is what the macOS tests run against), and a JSON file under the app's private files directory on Android.

The path comes through the existing Context binding (getFilesDir()), so this adds no bridge surface — consistent with the O(1)-bridge rule. Wiring it happens in MainActivity.onCreateSwift before the first view is built, so the opening evaluation already reads saved values rather than flashing defaults.

Reads and writes go through the same StateBox machinery @State uses, so changing a stored value marks the view dirty exactly like any other state write, and $value projects a normal Binding that writes through to disk.

Verification

  • swift test — 4 new tests, 105 passing: a fresh wrapper reads what a previous one wrote (the relaunch in miniature), all four types round-trip under independent keys, the projected binding writes through from a real TextField callback, and a second FileAppStorage instance reloads what the first wrote (including that removal sticks).
  • Emulator, the test that actually matters — incremented the counter to 3, confirmed files/app-storage.json contained {"demo.launches":3}, force-stopped the process (verified 0 processes alive), relaunched, and the counter still read 3. Then exercised the other types through their bindings, leaving {"demo.volume":0.926,"demo.notify":true,"demo.launches":4} on disk.

Scope

Four value types only — RawRepresentable, URL, and Data overloads aren't included, and there's no @SceneStorage. The file is rewritten whole on each write, which is fine for preferences and deliberately not a database. AppStorageStore.backend is process-wide, so it's set once at startup rather than per-view.

@colemancda
colemancda merged commit db5cc6f into master Jul 24, 2026
6 checks passed
@colemancda
colemancda deleted the feature/appstorage branch July 24, 2026 03:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant