swiftdatepickerswiftuiuidatepicker

DatePicker using Time-Interval in SwiftUI


I want to use a DatePicker in SwiftUI, it is working fine and as expected. I want to add an Time-interval, like explained: UIDatePicker 15 Minute Increments Swift

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

Is there a Modifier for that in SwifUI?


Solution

  • I don't believe there is a modifier for this. However it's possible to "do it yourself" by using UIViewRepresentable to wrap a UIDatePicker:

    The basic structure for this code is based on the Interfacing with UIKit tutorial.

    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()
        }
    }