3

I need an optional @AppStorage String property (for a NavigationLink selection, which required optional), so I declared

@AppStorage("navItemSelected") var navItemSelected: String?

I need it to start with a default value that's non-nil, so I tried:

@AppStorage("navItemSelected") var navItemSelected: String? = "default"

but that doesn't compile.

I also tried:

init() {
    if navItemSelected == nil { navItemSelected = "default" }
}

But this just overwrites the actual persisted value whenever the app starts.

Is there a way to start it with a default non-nil value and then have it persisted as normal?

Steve M
  • 9,296
  • 11
  • 49
  • 98
  • 1
    `Optional` is not plist type so cannot be stored in AppStorage, you need to solve this at `NavigationLink` side, say by introducing inline Binding checking conditionally value of AppStorage. – Asperi Oct 26 '21 at 16:29

2 Answers2

1

Here is a simple demo of possible approach based on inline Binding (follow-up of my comment above).

Tested with Xcode 13 / iOS 15

demo

struct DemoAppStoreNavigation: View {
    static let defaultNav = "default"
    @AppStorage("navItemSelected") var navItemSelected = Self.defaultNav

    var body: some View {
        NavigationView {
            Button("Go Next") {
                navItemSelected = "next"
            }.background(
                NavigationLink(isActive: Binding(
                    get: { navItemSelected != Self.defaultNav },
                    set: { _ in }
                ), destination: {
                    Button("Return") {
                        navItemSelected = Self.defaultNav
                    }
                    .onDisappear {
                        navItemSelected = Self.defaultNav   // << for the case of `<Back`
                    }
                }) { EmptyView() }
            )
        }
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690
0

@AppStorage is a wrapper for UserDefaults, so you can simply register a default the old-fashioned way:

UserDefaults.standard.register(defaults: ["navItemSelected" : "default"])

You will need to call register(defaults:) before your view loads, so I’d recommend calling it in your App’s init or in application(_:didFinishLaunchingWithOptions:).

Adam
  • 4,405
  • 16
  • 23