Средство выбора в NavigationView: не обновляется при изменении пользовательской привязки

#swift #swiftui

#swift #swiftui

Вопрос:

Я пытаюсь сохранить значение enum в UserDefaults. Для этого я создал пользовательскую привязку. Часть UserDefault работает нормально, но, к сожалению, значение в NavigationView не обновляется после изменения значения с помощью средства выбора.

Как я могу отобразить выбранное погодное условие?

PS: Если это не создает дополнительных сложностей, я бы хотел сохранить погоду перечисления типа Int.

 import SwiftUI

enum Weather: Int, CaseIterable {
    case rain
    case sun
    case clouds
}

func getWeatherText(weather: Weather) -> String {
    switch weather {
    case .rain: return "Rain"
    case .sun: return "Sun"
    case .clouds: return "Clouds"
    }
}

struct ContentView: View {
    let currentWeather = Binding<Weather>(
        get: {
            (Weather(rawValue: UserDefaults.standard.integer(forKey: "weather")) ?? .sun)
        },
        set: {
            UserDefaults.standard.set($0.rawValue, forKey: "weather")
        }
    )
    
    let weathers = Weather.allCases
    
    var body: some View {
        NavigationView{
            Form{
                Picker("Weather", selection: currentWeather) {
                    ForEach(weathers, id: .self) { w in
                        Text(getWeatherText(weather: w)).tag(w)
                    }
                }
            }
        }
    }
}
 

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

1. Разве вы не хотите вместо этого использовать AppStorage? Привязка не является динамическим свойством, поэтому она не приводит к принудительному перестроению тела представления. Вам нужно либо состояние, либо ObservedObject.

2. @AppStorage был именно тем, что мне было нужно. Спасибо!

Ответ №1:

Благодаря комментарию Asperi решение простое: заменить мою пользовательскую привязку на @AppStorage. Это результат:

 import SwiftUI

enum Weather: Int, CaseIterable {
    case rain
    case sun
    case clouds
}

func getWeatherText(weather: Weather) -> String {
    switch weather {
    case .rain: return "Rain"
    case .sun: return "Sun"
    case .clouds: return "Clouds"
    }
}

struct ContentView: View {
    @AppStorage("weather") var currentWeather: Weather = Weather.clouds
    
    let weathers = Weather.allCases
    
    var body: some View {
        NavigationView{
            Form{
                Picker("Weather", selection: $currentWeather) {
                    ForEach(weathers, id: .self) { w in
                        Text(getWeatherText(weather: w)).tag(w)
                    }
                }
            }
        }
    }
}