UserDefaults безумие, взять 2 с помощью DatePicker - PullRequest
0 голосов
/ 18 апреля 2020

Прогресс по безумию UserDefaults в SwiftUI, после предыдущего поста по основам c UserDefaults , который в основном выявил необходимость использования оболочки String () для значений UserDefaults ...

Теперь я потрясен потоком данных:

Идея состоит в том, чтобы представить DatePicker, установленный в значение UserDefaults, зарегистрированное в AppDelegate при первом запуске. Впоследствии пользователь выбирает другую дату, которая установлена ​​в UserDefaults. Но каждый раз, когда я запускаю приложение после того, как его «убили» (т. Е. Смахнули с переключателя приложений), средство выбора отображает текущую дату, а НЕ последнюю, сохраненную в UserDefaults.

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

1- В AppDelegate я регистрирую свои начальные значения UserDefaults (как я всегда делал в UIKit):

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch
        UserDefaults.standard.register(defaults: [
        "MyBool 1": true,
        "MyString": "Soo",
        "MyDate": Date()
        ])

        return true
    }

2- в ContentView, я попробуйте отобразить их:

import SwiftUI

struct ContentView: View {

    let defaults = UserDefaults.standard

    var dateFormatter: DateFormatter {
     let formatter = DateFormatter()
    // formatter.dateStyle = .long
     formatter.dateFormat = "dd MMM yy"
     return formatter
     }

    @State var selectedDate = Date()

    init() {
        self.loadData() // This should set "selectedDate" to the UserDefaults value
    }

    var body: some View {

        VStack {
            Text("The BOOL 1 value is : Bool 1 = \(String(defaults.bool(forKey: "MyBool 1")))")
            Divider()
            Text("My string says : \(String(defaults.string(forKey: "MyString")!))")
            Divider()
            Text("The date from UserDefaults is : \(dateFormatter.string(from: defaults.object(forKey: "MyDate") as! Date))")
            Divider()
            DatePicker(selection: $selectedDate, label: { Text("") })
                .labelsHidden()
                .onReceive([self.selectedDate].publisher.first()) { (value) in
                    self.saveDate()
                }

            Divider()
            Text("The chosen date is : \(selectedDate)")
        }
    }

    func loadData() {
        selectedDate = defaults.object(forKey: "MyDate") as! Date
        print("----> selected date in \"init\" from UserDefaults: \(dateFormatter.string(from: selectedDate) )) ")
    }

    private func saveDate() { // This func is called whenever the Picker sends out a value
        UserDefaults.standard.set(selectedDate, forKey: "MyDate")
        print("Saving the date to User Defaults : \(dateFormatter.string(from: selectedDate) ) ")
    }

}

Любая помощь будет оценена!

Ответы [ 3 ]

1 голос
/ 18 апреля 2020

попробуйте это:

struct ContentView: View {

    let defaults = UserDefaults.standard

    var dateFormatter: DateFormatter {
     let formatter = DateFormatter()
    // formatter.dateStyle = .long
     formatter.dateFormat = "dd MMM yy"
     return formatter
     }

    @State var selectedDate : Date

    init() {
        _selectedDate = State(initialValue: UserDefaults.standard.object(forKey: "MyDate") as! Date) // This should set "selectedDate" to the UserDefaults value
    }

    var body: some View {

        VStack {
            Text("The BOOL 1 value is : Bool 1 = \(String(defaults.bool(forKey: "MyBool 1")))")
            Divider()
            Text("My string says : \(String(defaults.string(forKey: "MyString")!))")
            Divider()
            Text("The date from UserDefaults is : \(dateFormatter.string(from: defaults.object(forKey: "MyDate") as! Date))")
            Divider()
            DatePicker(selection: $selectedDate, label: { Text("") })
                .labelsHidden()
                .onReceive([self.selectedDate].publisher.first()) { (value) in
                    self.saveDate()
                }

            Divider()
            Text("The chosen date is : \(selectedDate)")
        }
    }

    func loadData() {
        selectedDate = defaults.object(forKey: "MyDate") as! Date
        print("----> selected date in \"init\" from UserDefaults: \(dateFormatter.string(from: selectedDate) )) ")
    }

    private func saveDate() { // This func is called whenever the Picker sends out a value
        UserDefaults.standard.set(selectedDate, forKey: "MyDate")
        print("Saving the date to User Defaults : \(dateFormatter.string(from: selectedDate) ) ")
    }

}
1 голос
/ 18 апреля 2020

вот мой второй ответ, если вы хотите обновить текст также ... это не "хорошо" и, конечно, не лучший способ, но он работает (я проверял это)

struct ContentView: View {

    let defaults = UserDefaults.standard

    var dateFormatter: DateFormatter {
     let formatter = DateFormatter()
    // formatter.dateStyle = .long
     formatter.dateFormat = "dd MMM yy"
     return formatter
     }
    @State var uiUpdate : Int = 0
    @State var selectedDate : Date
    @State var oldDate : Date = Date()

    init() {
        _selectedDate = State(initialValue: UserDefaults.standard.object(forKey: "MyDate") as! Date) // This should set "selectedDate" to the UserDefaults value
    }

    var body: some View {

        VStack {
            Text("The BOOL 1 value is : Bool 1 = \(String(defaults.bool(forKey: "MyBool 1")))")
            Divider()
            Text("My string says : \(String(defaults.string(forKey: "MyString")!))")
            Divider()
            Text("The date from UserDefaults is : \(dateFormatter.string(from: defaults.object(forKey: "MyDate") as! Date))")
                .background(uiUpdate < 5 ? Color.yellow : Color.orange)
            Divider()
            DatePicker(selection: $selectedDate, label: { Text("") })
                .labelsHidden()
                .onReceive([self.selectedDate].publisher.first()) { (value) in
                    if self.oldDate != value {
                        self.oldDate = value
                        self.saveDate()
                    }
                }

            Divider()
            Text("The chosen date is : \(selectedDate)")
        }
    }

    func loadData() {
        selectedDate = defaults.object(forKey: "MyDate") as! Date
        print("----> selected date in \"init\" from UserDefaults: \(dateFormatter.string(from: selectedDate) )) ")
    }

    private func saveDate() { // This func is called whenever the Picker sends out a value
        UserDefaults.standard.set(selectedDate, forKey: "MyDate")
        print("Saving the date to User Defaults : \(dateFormatter.string(from: selectedDate) ) ")
        uiUpdate = uiUpdate + 1
    }

}
0 голосов
/ 18 апреля 2020

Каждый раз, когда вы запускаете приложение, оно заново регистрирует настройки по умолчанию. Вы можете использовать это:

    if !UserDefaults.standard.bool(forKey: "first time only") {
        UserDefaults.standard.register(defaults: [
            "first time only": true,
            "MyBool 1": true,
            "MyString": "Soo",
            "MyDate": Date()
        ])
    }
...