Zorgan
Zorgan

Reputation: 9123

'No exact matches in call to initializer' error on @AppStorage variable?

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?

Upvotes: 11

Views: 13808

Answers (3)

Mojtaba Hosseini
Mojtaba Hosseini

Reputation: 119350

This happens when one of the following conditions is not met:

  1. Missing default value on initialization:
@AppStorage("someKey") var someValue: Double // šŸ”“ Missing default value

@AppStorage("someKey") var someValue: Double? // āœ… the default value will be nil
@AppStorage("someKey") var someValue: Double = 1 // āœ… the default value will be 1.0
  1. The type of the Value is not one of the following types / or does not conform to the RawRepresentable where the RawValue type is one of the following:
āœ… where Value == TableColumnCustomization<RowValue>, RowValue : Identifiable

āœ… where Value == Bool
āœ… where Value == Int
āœ… where Value == Double
āœ… where Value == String
āœ… where Value == URL
āœ… where Value == Data
āœ… where Value : RawRepresentable, Value.RawValue == Int
āœ… where Value : RawRepresentable, Value.RawValue == String

// MARK: - Optional
āœ… where Value == Bool?
āœ… where Value == Int?
āœ… where Value == Double?
āœ… where Value == String?
āœ… where Value == URL?
āœ… where Value == Data?
āœ… where Value == R?, R : RawRepresentable, R.RawValue == String
āœ… where Value == R?, R : RawRepresentable, R.RawValue == Int

So any custom type should conform to RawRepresentable and the RawValue MUST be one of the above:

class MyType: RawRepresentable { // šŸ‘ˆ Conform to the required protocol

    typealias RawValue = String // šŸ‘ˆ Use one of the accepted types as the `RawValue`

    required init(rawValue: RawValue) {
        self.someValue = Int(rawValue)!
    }

    var rawValue: RawValue { "\(someValue)" }

    // MARK: Class Implementation
    var someValue: Int = 0
}

Now this works as expected:

@AppStorage("someKey") var someValue = MyType(rawValue: "1") // āœ… the default value of (inner) `someValue` will be 1

Upvotes: 3

Finbaz
Finbaz

Reputation: 326

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.

Upvotes: 5

Asperi
Asperi

Reputation: 257749

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)))
                    }
                }
            }
        }
    }
}

Upvotes: 4

Related Questions