Невозможно сохранить результат выбора в UserDefaults

#swiftui

#swiftui

Вопрос:

Я пытаюсь сохранить результат выбора в пользовательских значениях по умолчанию. Операция сохранения пользователя по умолчанию выполняется в классе UserData с помощью метода saveBase.

Я успешно попробовал аналогичную технику с помощью кнопки, но мой вызов после выбора выдает известную ошибку:

Тип ‘()’ не может соответствовать представлению.

 struct aboutView: View {

    @EnvironmentObject var userData: UserData

    @State private var baseEntry: Int = 0
    
    let base = ["Level 1", "Level 2","Level 3","Level 4"]
    
    var body: some View {
                
        Text("comment")
        Text("comment")
        Text("comment")

           
        Section {
            Picker(selection: $baseEntry, label: Text("Select Base >")) {
                ForEach(0 ..< self.base.count) {
                    Text(self.base[$0]).tag($0)
                    }
                    self.userData.saveBase(baseEntry: self.baseEntry)
                }
            }
            .padding()
    }
}
  
 class UserData:  ObservableObject {
    @Published var baseCurr: Int

    func saveBase(baseEntry: Int) -> () {
        
        baseCurr = baseEntry

        let defaults = UserDefaults.standard
        defaults.set(self.baseCurr, forKey: "base")
    }
}
  

Ответ №1:

В body вы можете использовать только представления — вы не можете выполнять такие операции, как:

 self.userData.saveBase(baseEntry: self.baseEntry)
  

Вы можете использовать onChange для сохранения значения:

 Picker(selection: $baseEntry, label: Text("Select Base >")) {
    ForEach(0 ..< self.base.count) {
        Text(self.base[$0]).tag($0)
    }
    .onChange(of: baseEntry) {
        self.userData.saveBase(baseEntry: $0)
    }
}
  

Обратите внимание, что вы также можете использовать @AppStorage для автоматизации сохранения / чтения из UserDefaults:

 @AppStorage("base") var baseEntry = 0
  

и использовать в сборщике так же, как @State переменную:

 Picker(selection: $baseEntry, label: Text("Select Base >")) {
  

Комментарии:

1. @AppStorage отлично работает, но не обновляет мой параметр, хранящийся в классе UserData (userData.BaseCurr). .onChange обладает наибольшим потенциалом, но поскольку мы используем локальный частный параметр состояния (baseEntry), он не обновляется userData.BaseCurr

2. @GalenSmith Вам, вероятно, не нужна отдельная @State переменная в представлении. Просто сделайте Picker(selection: $userData.baseCurr и наблюдайте, как .onChange(of: userData.baseCurr) {

3. Средство выбора (выделение: $userData.BaseCurr, метка: текст («Валюта>»)) { ForEach(0 ..< self.baseCurrencies.count) { Текст (self.baseCurrencies[$0]).тег ($ 0). не может соответствовать ‘Equatable } . onChange(of: self.userData.BaseCurr: Int) { self.userData.saveBase() —> выдает сообщение: не удается преобразовать значение типа ‘Int’ в ожидаемый тип аргумента ‘()’.

4. Использование @GalenSmith .onChange(of: userData.baseCurr) { userData.saveBase(baseEntry: $0) }

5. Спасибо pawello2222 за помощь. Я наконец-то заработал. Я использовал userData.BaseCurr как в сборщике, так и в onChange. Если метод user data.saveBase вызывается без параметров, SwiftUI выдает две ошибки, перечисленные выше; если я оставлю @State private var baseEntry: $0 в качестве заполнителя в вызове, все работает нормально.