ios 如果以编程方式设置选择,则不调用MultiDatePicker onChange

mm9b1k5b  于 2022-12-20  发布在  iOS
关注(0)|答案(2)|浏览(88)

我试着选择一个日期(今天)。选择按预期工作,onChange修饰符将被调用,今天在选择器中被标记为已选中。但是,当我尝试直接在MultiDatePicker中取消选择日期时,日期不再被标记,但onChange修饰符将不会被调用。如果您现在点击MultiDatePicker中的另一个日期,则两个日期(另一个日期和今天的日期被标记为被选择。

import SwiftUI

struct ContentView: View {

    @Environment(\.calendar) private var calendar

    @State private var selectedDates: Set<DateComponents> = []

    @State private var onChangeCounter = 0
    
    var body: some View {
        VStack {
            MultiDatePicker("Select dates", selection: $selectedDates)
                .frame(height: UIScreen.main.bounds.width)
                .onChange(of: selectedDates) { _ in
                    self.onChangeCounter += 1
                }

            Button("Select today") {
                let todayDatecomponents = calendar.dateComponents(in: calendar.timeZone, from: Date.now)
                selectedDates.insert(todayDatecomponents)
            }
            .foregroundColor(.white)
            .frame(minWidth: 150)
            .padding()
            .background(Color.accentColor)
            .cornerRadius(20)

            HStack {
                Text("onChangeCounter")
                Spacer()
                Text(String(onChangeCounter))
            }
            .padding()

            Spacer()
        }
    }
}

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

我是否做错了什么,或者只是无法以编程方式在MultiDatePicker中选择日期?
谢谢你!

ioekq8ef

ioekq8ef1#

在本次讨论中,今天是指*2022年12月17日***
问题是Date.now不等于
今天**
我在美国东海岸时区...如果我向print(Date.now)添加一个按钮并点击它,我会在调试控制台中看到以下内容:

2022-12-17 14:08:52 +0000

如果我4秒后再次点击它,我会看到:

2022-12-17 14:08:56 +0000

这两个日期***不***相等。
那么,让我们看看MultiDatePicker使用的是什么,因为它是selection
将您的MultiDatePicker更改为:

MultiDatePicker("Select dates", selection: $selectedDates)
            .frame(height: UIScreen.main.bounds.width)
            .onChange(of: selectedDates) { _ in
                print("onChange")
                selectedDates.forEach { d in
                    print(d)
                }
                print()
                self.onChangeCounter += 1
            }

如果我运行应用程序并选择Dec 14、19和8,我会看到以下内容:

onChange
calendar: gregorian (current) era: 1 year: 2022 month: 12 day: 14 isLeapMonth: false 

onChange
calendar: gregorian (current) era: 1 year: 2022 month: 12 day: 14 isLeapMonth: false 
calendar: gregorian (current) era: 1 year: 2022 month: 12 day: 19 isLeapMonth: false 

onChange
calendar: gregorian (current) era: 1 year: 2022 month: 12 day: 14 isLeapMonth: false 
calendar: gregorian (current) era: 1 year: 2022 month: 12 day: 19 isLeapMonth: false 
calendar: gregorian (current) era: 1 year: 2022 month: 12 day: 8 isLeapMonth: false

现在,我取消选择第19个,我看到:

onChange
calendar: gregorian (current) era: 1 year: 2022 month: 12 day: 14 isLeapMonth: false 
calendar: gregorian (current) era: 1 year: 2022 month: 12 day: 8 isLeapMonth: false

第19个被正确地从Set中删除。
现在,我点击“选择今天”按钮,我看到这个:

onChange
calendar: gregorian (current) era: 1 year: 2022 month: 12 day: 14 isLeapMonth: false 
calendar: gregorian (current) era: 1 year: 2022 month: 12 day: 8 isLeapMonth: false 
calendar: gregorian (current) timeZone: America/New_York (fixed (equal to current)) era: 1 year: 2022 month: 12 day: 17 hour: 9 minute: 24 second: 11 nanosecond: 339460015 weekday: 7 weekdayOrdinal: 3 quarter: 0 weekOfMonth: 3 weekOfYear: 51 yearForWeekOfYear: 2022 isLeapMonth: false

我们可以看到,这两条线:

let todayDatecomponents = calendar.dateComponents(in: calendar.timeZone, from: Date.now)
selectedDates.insert(todayDatecomponents)

插入DateComponents对象,包含批次更多详细信息。
如果我再次点击“选择今天”,我会看到:

onChange
calendar: gregorian (current) era: 1 year: 2022 month: 12 day: 8 isLeapMonth: false 
calendar: gregorian (current) era: 1 year: 2022 month: 12 day: 14 isLeapMonth: false 
calendar: gregorian (current) timeZone: America/New_York (fixed (equal to current)) era: 1 year: 2022 month: 12 day: 17 hour: 9 minute: 24 second: 11 nanosecond: 339460015 weekday: 7 weekdayOrdinal: 3 quarter: 0 weekOfMonth: 3 weekOfYear: 51 yearForWeekOfYear: 2022 isLeapMonth: false 
calendar: gregorian (current) timeZone: America/New_York (fixed (equal to current)) era: 1 year: 2022 month: 12 day: 17 hour: 9 minute: 26 second: 39 nanosecond: 866878032 weekday: 7 weekdayOrdinal: 3 quarter: 0 weekOfMonth: 3 weekOfYear: 51 yearForWeekOfYear: 2022 isLeapMonth: false

现在selectedDates包含两个“今天日期”...间隔2分28秒。
当我点击日历上的17号时,在那个set中没有匹配的日期要删除...所以当日历刷新时(比如当我选择另一个日期时),17号仍然显示为选中。
因此,让我们更改以编程方式插入的DateComponents,以匹配日历的数据:

let todayDatecomponents = calendar.dateComponents([.calendar, .era, .year, .month, .day], from: Date.now)
selectedDates.insert(todayDatecomponents)

现在,当我们点击日历上的17时,它将被取消选择***,***匹配的对象selectedDates将被删除。
下面是我如何修改代码以进行调试:

import SwiftUI

@available(iOS 16.0, *)
struct MultiDateView: View {
    @Environment(\.calendar) private var calendar
    
    @State private var selectedDates: Set<DateComponents> = []
    
    @State private var onChangeCounter = 0
    
    var body: some View {
        VStack {
            MultiDatePicker("Select dates", selection: $selectedDates)
                .frame(height: UIScreen.main.bounds.width)
                .onChange(of: selectedDates) { _ in
                    print("onChange")
                    selectedDates.forEach { d in
                        print(d)
                    }
                    print()
                    self.onChangeCounter += 1
                }
            
            Button("Select today") {
                let todayDatecomponents = calendar.dateComponents(in: calendar.timeZone, from: Date.now)
                selectedDates.insert(todayDatecomponents)
            }
            .foregroundColor(.white)
            .frame(minWidth: 150)
            .padding()
            .background(Color.accentColor)
            .cornerRadius(20)
            
            Button("Select today the right way") {
                let todayDatecomponents = calendar.dateComponents([.calendar, .era, .year, .month, .day], from: Date.now)
                selectedDates.insert(todayDatecomponents)
            }
            .foregroundColor(.white)
            .frame(minWidth: 150)
            .padding()
            .background(Color.green)
            .cornerRadius(20)
            
            HStack {
                Text("onChangeCounter")
                Spacer()
                Text(String(onChangeCounter))
            }
            .padding()
            
            Button("Print Date.now in debug console") {
                print("debug")
                print("debug:", Date.now)
                print()
            }
            .foregroundColor(.white)
            .frame(minWidth: 150)
            .padding()
            .background(Color.red)
            .cornerRadius(20)
            
            Spacer()
        }
    }
}

@available(iOS 16.0, *)
struct MultiDateView_Previews: PreviewProvider {
    static var previews: some View {
        MultiDateView()
    }
}
zzzyeukh

zzzyeukh2#

看起来MultiDatePicker节省了额外的组件。
使用此选项设置今天的组件:

let todayDatecomponents = calendar.dateComponents([.calendar, .era, .year, .month, .day], from: .now)

相关问题