【问题标题】:View parameter only passed to view when application first loads - SwiftUI视图参数仅在应用程序首次加载时传递给视图 - SwiftUI
【发布时间】:2021-01-29 08:16:10
【问题描述】:

我有一个导航视图(SettingsView),如下所示。当我第一次去 PayScheduleForm 时,来自 UserDefaults 的日期被正确传递。如果我更改 PayScheduleForm 中的 payDate 值,我可以看到它正确更新了 UserDefaults 键。但是,如果我返回 SettingsView,然后再次转到 PayScheduleForm,原始值仍会显示在选取器中。

这是一个奇怪的场景,所以最好逐步解释:

  1. 启动应用程序
  2. 转到设置 -> 支付时间表
  3. 最后一个 UserDefaults payDate 值在 DatePicker (10/08/2020) 中
  4. 将值更改为 10/14/2020 - 控制台显示 UserDefaults.standard.object(forKey: "payDate") = 10/14/2020 字符串
  5. 返回设置(使用返回按钮)
  6. 返回 Pay Schedule 并查看 DatePicker 具有其原始值 (10/08/2020)
  7. 当然,如果我再次重新启动应用程序,我会在 DatePicker 中看到 10/14/2020
struct SettingsView: View {

    
    var body: some View {
        NavigationView{
            if #available(iOS 14.0, *) {
                List{
                    NavigationLink(destination: AccountsList()) {
                        Text("Accounts")
                    }
                    NavigationLink(destination: CategoriesList()) {
                        Text("Categories")
                    }
                    NavigationLink(destination: PayScheduleForm(date: getPayDate()).onAppear(){
                        getPayDate()
                        
                    }) {
                        
                        Text("Pay Schedule")
                    }
                }.navigationTitle("Settings")
            } else {
                // Fallback on earlier versions
            }
            
        }.onAppear(perform: {
            getUserDefaults()
        })
    }
    
    func getPayDate() -> Date{
        var date = Date()
        if UserDefaults.standard.object(forKey: "payDate") != nil {
            date = UserDefaults.standard.object(forKey: "payDate") as! Date
        }
        let df = DateFormatter()
        df.dateFormat = "MM/dd/yyyy"
        print(df.string(from: date))
        
        return date
    }
struct PayScheduleForm: View {
    var frequencies = ["Bi-Weekly"]
    
    @Environment(\.managedObjectContext) var context
    
    
    @State var payFrequency: String?
    @State var date: Date
    
    var nextPayDay: String{
        let nextPaydate = (Calendar.current.date(byAdding: .day, value: 14, to: date ))
        return Utils.dateFormatterMed.string(from: nextPaydate ?? Date() )
    }
    var body: some View {
        Form{
            Picker(selection: $payFrequency, label: Text("Pay Frequency")) {
                if #available(iOS 14.0, *) {
                    ForEach(0 ..< frequencies.count) {
                        Text(self.frequencies[$0]).tag(payFrequency)
                    }.onChange(of: payFrequency, perform: { value in
                        UserDefaults.standard.set(payFrequency, forKey:"payFrequency")
                        print(UserDefaults.standard.string(forKey:"payFrequency")!)
                    })
                } else {
                    // Fallback on earlier versions
                }
                }
            if #available(iOS 14.0, *) {
                DatePicker(selection: $date, displayedComponents: .date) {
                    Text("Last Payday")
                }
                
                .onChange(of: date, perform: { value in
                    UserDefaults.standard.set(date, forKey: "payDate")
                    let date = UserDefaults.standard.object(forKey: "payDate") as! Date
                    let df = DateFormatter()
                    df.dateFormat = "MM/dd/yyyy"
                    print(df.string(from: date))
                })
            } else {
                // Fallback on earlier versions
            }
            
            
            
        }
    ```

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    解决了这个问题。发帖让其他有相同问题的人可以找到答案。

    iOS 14 允许 @AppStorage 属性包装器,它可以轻松访问 UserDefaults,但到目前为止,@AppStorage 不允许使用 Date 类型。

    相反,您可以使用@Observable 对象

    首先创建一个名为 UserSettings.swift 的 swift 文件并在其中创建一个类:

    class UserSettings: ObservableObject {
        @Published var date: Date {
            didSet {
                UserDefaults.standard.set(date, forKey: "payDate")
            }
        }
        
        init() {
            self.date = UserDefaults.standard.object(forKey: "payDate") as? Date ?? Date()
        }
    }
    

    然后将@ObservableObject 添加到您的视图中

        @ObservedObject var userSettings = UserSettings()
    ...
    
                DatePicker(selection: $userSettings.date, displayedComponents: .date) {
                        Text("Last Payday")
                    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-23
      • 1970-01-01
      • 1970-01-01
      • 2022-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-27
      相关资源
      最近更新 更多