【问题标题】:ObservableObject with DatePicker in SwiftUI在 SwiftUI 中使用 DatePicker 的 ObservableObject
【发布时间】:2021-11-07 10:15:14
【问题描述】:

你能帮我提供以下源代码吗:

import SwiftUI


class DateHandler {
    
    /* create a variable
     Class to manage start date and end date
    */
    

    var date1 : Date {
        didSet{
            print("StartDate: \(date1)")
        }
    }
    var date2 : Date {
        didSet{
            print("EndDate: \(date2)")
        }
    }
    
    var startDate:Date {
        get{
            return date1
        }
        
        set(newValue){
            date1 = toLocalTime(date: newValue)
        }
        
    }
    
    var endDate:Date {
        get{
            return date2
        }
        
        set(newValue){
            date2 = addOneDay(date: toLocalTime(date: newValue))
        }
        
    }
    
    init(){
        self.date1 = Date()
        self.date2 = Date()
    }
    
    
    //Customize time zone
    func toLocalTime(date : Date) -> Date {
    
        
        //Auswahl der aktuellen Kalender
        let calendar = Calendar.current
        
        //Auswahl der Zeitzone
        let timezone = TimeZone.current
        
        //Bestimmen Anzahl Sekunden zwischen Zeitzone und GMT
        let seconds = TimeInterval(timezone.secondsFromGMT(for: date))
        
        //Anpassen des eingelesenen Werts
        let newDate = calendar.date(bySettingHour: 00, minute: 00, second: 00, of: date)
        let dateLocalTimezone = Date(timeInterval: seconds, since: newDate!)

        return dateLocalTimezone
    }
    
    func addOneDay(date : Date) -> Date {

        let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: date)
        return tomorrow!
    }

}

//Class to use DateHandler() as a ObservableObject
class DateHandlerHelper : ObservableObject{
    
    @Published var dateHandler = DateHandler()
    
}



struct ContentView: View {
    
    @ObservedObject var dateHandlerHelper = DateHandlerHelper()
    
    @State var startDateHelper = Date()
    @State var endDateHelper = Date()
    

    var body: some View {
        
        DatePicker("Date1", selection: $startDateHelper)
            .onAppear(perform: {
                print("onAppear")
                dateHandlerHelper.dateHandler.startDate = startDateHelper
                print(dateHandlerHelper.dateHandler.startDate)
                
            })
            .onChange(of: startDateHelper) { newValue in
                
                print("onChange")
                
                dateHandlerHelper.dateHandler.startDate = newValue
                
                if newValue > endDateHelper{
                    print("Correction Date 1")
                    startDateHelper = endDateHelper
                    dateHandlerHelper.dateHandler.startDate = endDateHelper
                    
                    
                }
                

                print(dateHandlerHelper.dateHandler.startDate)
            }
        
        
        DatePicker("Date2", selection: $endDateHelper)
            .onAppear(perform: {
                
                dateHandlerHelper.dateHandler.endDate = endDateHelper
                print(dateHandlerHelper.dateHandler.endDate)
            })
            .onChange(of: endDateHelper) { newValue in
                print("onChange")
                dateHandlerHelper.dateHandler.endDate = newValue
                print(dateHandlerHelper.dateHandler.endDate)
            }
                
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

我有一个带有两个 DatePicker 的视图来选择开始日期和结束日期。对于开始日期和结束日期,有 DateHandler 类。

我想将 DateHandler 类作为 ObservableObject 处理。由于使用了getter/setter函数,我只能通过DateHandlerHelper类间接寻址DateHandler类。这里有更好/更简单的方法吗?

如果我直接通过 DatePickers 处理变量 dateHandlerHelper.dateHandler.startDate 和 dateHandlerHelper.dateHandler.endDate,我可以更改值,但 DatePickers 本身不会更新。为此,我在视图中引入了变量 startDateHelper 和 endDateHelper。你知道我可以如何以不同的方式来保存变量吗?

【问题讨论】:

    标签: swiftui datepicker


    【解决方案1】:

    我不明白为什么每次都需要进行这些日期计算,而是我更改了它们以便在初始化 DateHelper 类时完成一次。

    class DateHandler: ObservableObject {
        @Published var startDate: Date
        @Published var endDate: Date
    
        init(){
            startDate = Self.toLocalTime(date: .now)
            //I assume endDate also should be adjusted for local time?
            let date = Self.addOneDay(date: .now) 
            endDate = Self.toLocalTime(date: date)
        }
    
        private static func toLocalTime(date : Date) -> Date {
            // removed for brevity
        }
    
        private static func addOneDay(date : Date) -> Date {
            // removed for brevity
        }
    }
    

    然后视图会简单得多

    struct ContentView: View {
        @ObservedObject var dateHandler = DateHandler()
    
        var body: some View {
            VStack {
                DatePicker("Date1", selection: $dateHandler.startDate)
                DatePicker("Date2", selection: $dateHandler.endDate)
            }
        }
    }
    

    【讨论】:

    • 我已根据您的建议修改了代码。该方法原则上有效。但是,显然没有正确调用函数 addOneDay(date)。因此,我最初使用的是 getter/setter 函数。这个想法是,例如,如果通过 DatePicker Date2 选择日期 2021-11-09,则调用函数 addOneDay(date),然后将日期更正为 2021-11-10 00:00:00 +0000。这不起作用。
    • 好的。我不确定你为什么要增加一天,所以上面的解决方案只是我的假设。我仍然不认为每次用户更改日期时都需要这样做,因为更改对用户是不可见的。因此,一种解决方案可能是添加一个函数或计算属性correctedEndDate,它将一天添加到属性endDate,然后在您需要在代码中使用日期时调用它。话虽如此,我觉得用户看不到他们选择的实际日期有点奇怪,但也许你有这样做的原因。
    【解决方案2】:

    这似乎是正确的方法:

    class DateModel : ObservableObject{
    
    var date1 : Date{
        didSet{
            print(date1)
        }
    }
    var date2 : Date{
        didSet{
            print(date2)
        }
    }
    
    var startDate:Date {
        get{
            return date1
        }
        
        set(newValue){
        
            date1 = toLocalTime(date: newValue)
            startDateString = date1.toString()
            print(startDateString)
                
        }
        
    }
    
    
    var endDate:Date {
        get{
            return date2
        }
        
        set(newValue){
            date2 = toLocalTime(date: newValue)
        }
        
    }
    
    init(){
        self.date1 = Date()
        self.date2 = Date()
    }
    
    
    
    //Customize time zone
    func toLocalTime(date : Date) -> Date {
    
        //Selection of the current calendar
        let calendar = Calendar.current
        
        //Time zone selection
        let timezone = TimeZone.current
        
        //Determine number of seconds between time zone and GMT
        let seconds = TimeInterval(timezone.secondsFromGMT(for: date))
        
        //Adjusting the input value
        let newDate = calendar.date(bySettingHour: 00, minute: 00, second: 00, of: date)
        let dateLocalTimezone = Date(timeInterval: seconds, since: newDate!)
    
        return dateLocalTimezone
    }
    
    }
    
    struct ContentView: View {
    
    @ObservedObject var dateModel = DateModel()
    
    var dateFormatter: DateFormatter {
        let formatter = DateFormatter()
        formatter.dateStyle = .long
        return formatter
    }
    
    var body: some View {
        
        Form{
            Section{
                
                DatePicker("start date", selection: $dateModel.startDate, displayedComponents: [.date]).onChange(of: dateModel.startDate) { newValue in
                    print(newValue.toString())
                }
                
                DatePicker("final date", selection: $dateModel.endDate, displayedComponents: [.date])
                
    
                
    
            }
            
        }
                
    }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-07-06
      • 2022-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多