Jonas Deichelmann
Jonas Deichelmann

Reputation: 3743

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?

Upvotes: 11

Views: 8709

Answers (4)

DILIP KOSURI
DILIP KOSURI

Reputation: 465

I think, the below will help..

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

Upvotes: 2

imike
imike

Reputation: 5656

It is also possible with Introspect lib

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

Upvotes: 2

DarkAgeOutlaw
DarkAgeOutlaw

Reputation: 587

Not fully a SwiftUI solution, but much simpler than the existing answer. Attach this to your main body View that contains the picker

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

The one downside is this will apply to all pickers in the view and can affect pickers in other views in the app, but you can always do the same thing in those views (set minute interval back to 1).

Upvotes: 12

jtbandes
jtbandes

Reputation: 118681

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

Upvotes: 13

Related Questions