SwiftUI中使用时间间隔的日期选择器

11

我想在SwiftUI中使用DatePicker,它正常工作并如预期一样。我想添加一个时间间隔,就像这里解释的那样:UIDatePicker 15 Minute Increments Swift

DatePicker("Please enter a time", selection: $wakeUp, displayedComponents: .hourAndMinute)

在SwifUI中有相应的修饰符吗?

4个回答

13

我不相信有这方面的修饰符。但是可以通过使用UIViewRepresentable包装UIDatePicker来"自己动手"实现:

此代码的基本结构基于与UIKit交互教程。

struct MyDatePicker: UIViewRepresentable {

    @Binding var selection: Date
    let minuteInterval: Int
    let displayedComponents: DatePickerComponents

    func makeCoordinator() -> Coordinator {
        return Coordinator(self)
    }

    func makeUIView(context: UIViewRepresentableContext<MyDatePicker>) -> UIDatePicker {
        let picker = UIDatePicker()
        // listen to changes coming from the date picker, and use them to update the state variable
        picker.addTarget(context.coordinator, action: #selector(Coordinator.dateChanged), for: .valueChanged)
        return picker
    }

    func updateUIView(_ picker: UIDatePicker, context: UIViewRepresentableContext<MyDatePicker>) {
        picker.minuteInterval = minuteInterval
        picker.date = selection

        switch displayedComponents {
        case .hourAndMinute:
            picker.datePickerMode = .time
        case .date:
            picker.datePickerMode = .date
        case [.hourAndMinute, .date]:
            picker.datePickerMode = .dateAndTime
        default:
            break
        }
    }

    class Coordinator {
        let datePicker: MyDatePicker
        init(_ datePicker: MyDatePicker) {
            self.datePicker = datePicker
        }

        @objc func dateChanged(_ sender: UIDatePicker) {
            datePicker.selection = sender.date
        }
    }
}

struct DatePickerDemo: View {
    @State var wakeUp: Date = Date()
    @State var minterval: Int = 1

    var body: some View {
        VStack {
            Stepper(value: $minterval) {
                Text("Minute interval: \(minterval)")
            }
            MyDatePicker(selection: $wakeUp, minuteInterval: minterval, displayedComponents: .hourAndMinute)
            Text("\(wakeUp)")
        }
    }
}

struct DatePickerDemo_Previews: PreviewProvider {
    static var previews: some View {
        DatePickerDemo()
    }
}


谢谢@jtbandes,这是符合我的要求的解决方案。一般来说,我不希望自己去做它。 - Jonas Deichelmann
@jtbandes 这是一个很好的解决方案!但是,由于某种原因,MyDatePicker占据了整个SwiftUI视图(选择器本身的大小是正常的,但它会将其周围的所有内容推出并填充整个视图空间)。有什么想法和方法可以修复吗?我很想使用这个! - winston
找到解决方案了!请添加以下修饰符来缩小其大小:.frame(height: 100).mask(Rectangle())。再次感谢您提供的出色解决方案! - winston

11

不完全是SwiftUI解决方案,但比现有答案简单得多。将此附加到包含选择器的主体视图中。

.onAppear {
    UIDatePicker.appearance().minuteInterval = 5
}

唯一的缺点就是这将应用于视图中的所有选择器,并且可能会影响应用程序中其他视图中的选择器,但您可以在这些视图中执行相同的操作(将分钟间隔设置回1)。


谢谢!我实际上将其添加到我的“视图”的“初始化器”中,它仍然可以工作。 - Idelfonso Gutierrez

2

我认为以下内容会有所帮助...

struct DatePickerView: View {
    @Binding var dateSelected: Date
    var type: DatePickerComponents? = .date

    var body: some View {
        DatePicker("", selection: $dateSelected, displayedComponents: .hourAndMinute)
            .datePickerStyle(.wheel)
            .onAppear {
                if type == .hourAndMinute {
                    UIDatePicker.appearance().minuteInterval = 15
                } else {
                    UIDatePicker.appearance().minimumDate = dateSelected
                }
            }
    }
}

2

使用 Introspect 库也可以实现这个功能。

DatePicker(...)
    .introspectDatePicker {
        $0.minuteInterval = 30
        $0.roundsToMinuteInterval = true
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接