Reputation: 9123
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
Reputation: 119350
This happens when one of the following conditions is not met:
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
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
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
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