通过didSet on@Published var将日期/时间保存到用户默认设置(来自SwiftUI的TimePicker组件) [英] Saving Date/Time to UserDefaults through didSet on @Published var (from TimePicker component of SwiftUI)
问题描述
我正在尝试保存用户的签入时间首选项(向他们发送通知提醒)。到目前为止,我已经能够将Bool和字符串保存到UserDefaults,但我不知道如何节省时间首选项。这是我用于存储首选项的UserSetting类。
public class UserSettings: ObservableObject {
@Published var eveningCheckin: Bool {
didSet{
UserDefaults.standard.set(eveningCheckin, forKey: "eveningCheckin")
print("Evening checkin toggle value in didSET to (self.eveningCheckin)")
}
}
@Published var eveningCheckinTime: Date {
didSet{
UserDefaults.standard.set(eveningCheckinTime, forKey: "eveningCheckinTime")
print("Evening checkin didSet to (self.eveningCheckinTime)")
}
}
init() {
self.eveningCheckin = UserDefaults.standard.object(forKey: "eveningCheckin") as? Bool ?? false
self.eveningCheckinTime = UserDefaults.standard.object(forKey: "eveningCheckinTime") as? Date ?? Date(timeIntervalSince1970: 64800)
print("Evening checkin time init to (self.eveningCheckinTime)")// --> To debug
print("Evening checkin toggle value in init to (self.eveningCheckin)")
}
}
我想用SwiftUI提供的时间选择器设置这个晚上的签到时间,如下所示。以下是我的设置和计时器视图。
import SwiftUI
struct SettingsMain: View {
@ObservedObject var userSettings = UserSettings()
@State private var showTimepickerEvening = false
var body: some View {
NavigationView{
ScrollView {
VStack {
//Evening checkins
Button(action: {
//Show 🌙 Evening time picker sheet
self.showTimepickerEvening.toggle()
}) {
HStack {
Text("(userSettings.eveningCheckinTime.hour12):(userSettings.eveningCheckinTime.minute0x) (userSettings.eveningCheckinTime.amPM.lowercased()) ")
Text("Change >")
}
}
.sheet(isPresented: $showTimepickerEvening) {
//Sheet view with the Timepicker
TimePickerView(pickedTime: self.$userSettings.eveningCheckinTime)
}
}
.buttonStyle(PlainButtonStyle())
}
.navigationBarTitle("Preferences", displayMode: .inline)
}
}
}
struct TimePickerView: View {
@Environment(.presentationMode) var presentationMode: Binding<PresentationMode>
@Binding var pickedTime: Date
var body: some View {
VStack {
DatePicker("Checkin time", selection: $pickedTime, displayedComponents: .hourAndMinute)
.labelsHidden()
Button(action: {
//Dimiss. Should I actually update my UserDefaults here as well?
self.presentationMode.wrappedValue.dismiss()
}) {
ZStack {
ColorManager.buttonGrey
Text("Save time")
.font(.system(size: 20))
.fontWeight(.semibold)
}
.frame(height: 64)
}
.padding(.all)
.buttonStyle(PlainButtonStyle())
}
.background(Color.white)
}
}
我的问题是,时间选择器确实将时间设置为@Published变量,但它使用init语句重置了时间。布尔值不会发生这种情况。为什么??
以下是上述print()语句的输出:基本上意味着每次我尝试使用datepicker设置时间时-&>didSet确实选择了新时间,但init()将其重置为默认时间。
晚上签到已设置为1970-01-01 12:12:00+0000
晚上签到时间从1970-01-01 18:00:00+0000
夜间签入将init中的值切换为True
晚上签到已设置为1970-01-01 12:13:00+0000
晚上签到时间从1970-01-01 18:00:00+0000
夜间签入将init中的值切换为True
推荐答案
如何存储和批注视图模型的问题。您永远不应该在View
本身中创建@ObservedObject
,而应该注入它。每当@ObservedObject
的@Published
属性更改时,存储该对象的View
将被重新加载-这意味着如果您正在初始化View
中的@ObservedObject
,则将创建该对象的新实例。
您需要将对象注入到视图中,以避免每次刷新视图时都重新创建它。
struct SettingsMain: View {
@ObservedObject var userSettings: UserSettings
@State private var showTimepickerEvening = false
...
从您创建SettingsMain
的任何位置(我们将其称为MainView
作为说明),在那里创建UserSettings
并将其注释为@State
(或者,如果您从View
以外的其他对象创建它,则假设它是一个ViewModel,则将其创建为@Published
):
struct MainView: View {
@State var userSettings = UserSettings()
var body: some View {
SettingsMain(userSettings: userSettings)
}
}
这篇关于通过didSet on@Published var将日期/时间保存到用户默认设置(来自SwiftUI的TimePicker组件)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!