8

I'm getting the following error: No exact matches in call to initializer on my @AppStorage variable below:

Model.swift

class UserSettings: ObservableObject {
    @AppStorage("minAge") var minAge: Float = UserDefaults.standard.float(forKey: "minAge") 

This variable is meant to bind to a Slider value below.

Settings.swift

import SwiftUI
struct Settings: View {
    let auth: UserAuth
    init(auth: UserAuth) {
        self.auth = auth
    }
    @State var minAge = UserSettings().minAge
    let settings = UserSettings()

    var body: some View {
            VStack {
                NavigationView {
                    Form {
                        Section {
                        Text("Min age")
                        Slider(value: $minAge, in: 18...99, step: 1, label: {Text("Label")})
                            .onReceive([self.minAge].publisher.first()) { (value) in
                                UserDefaults.standard.set(self.minAge, forKey: "minAge")
                            }
                        Text(String(Int(minAge)))
                        }

Any idea what the problem is?

Zorgan
  • 8,227
  • 23
  • 106
  • 207
  • This seems a slight catch-all error: I've also had it when declaring an optional property with an initial value (Bool? = true) – green_knight Apr 30 '22 at 19:08

2 Answers2

5

I am also seeing the same error with the following:

@AppStorage ("FavouriteBouquets") var favouriteBouquets: [String] = []()

Perhaps an array of Strings is not supported by AppStorage.

Edit Found the answer here.

Finbaz
  • 301
  • 1
  • 3
  • 10
  • 1
    You can also conform `Array` to `RawRepresentable` like in here: https://stackoverflow.com/a/62563773/8697793 – pawello2222 Jan 06 '21 at 15:39
4

You don't need intermediate state and UserDefaults, because you can bind directly to AppStorage value and it is by default uses UserDefaults.standard. Also you need to use same types with Slider which is Double.

So, here is a minimal demo solution. Tested with Xcode 12.

struct Settings: View {
    @AppStorage("minAge") var minAge: Double = 18

    var body: some View {
        VStack {
            NavigationView {
                Form {
                    Section {
                        Text("Min age")
                        Slider(value: $minAge, in: 18...99, step: 1, label: {Text("Label")})
                        Text(String(Int(minAge)))
                    }
                }
            }
        }
    }
}

Asperi
  • 228,894
  • 20
  • 464
  • 690
  • Thankyou this works. How do you know that `Double` is required? Doesn't say in the`Slider` doc: https://developer.apple.com/documentation/swiftui/slider – Zorgan Jul 09 '20 at 08:26
  • It's very much implied (Apple binds the slider to a value that's a Double), and when I changed that to Int, my app failed to compile with _Initializer 'init(value:in:onEditingChanged:)' requires that 'Int' conform to 'BinaryFloatingPoint'_. This means you can use Double, Float, or CGFloat – green_knight Apr 30 '22 at 19:13