Datepicker Using Time-Interval in Swiftui

DatePicker using Time-Interval in SwiftUI

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

Specific times in a DatePicker()

You can't specify selected times in DatePicker.

But you could do something like this instead and and combine the values on commit:

struct ContentView: View {

@State private var date = Date()
@State private var time = "8:00"

var body: some View {
HStack {
DatePicker("Select", selection: $date, displayedComponents: .date)
.datePickerStyle(.compact)
.background(.background)

Picker("Time", selection: $time) {
Text("2:00").tag("2:00")
Text("8:00").tag("8:00")
Text("11:00").tag("11:00")
}
.pickerStyle(.wheel)
.frame(width: 100)
.zIndex(-1)
}
.padding()
}
}

Time Intervals SwiftUI

You have the wrong logic in if, so "15:30" goes into ContentView2. The correct logic may look like this:

if (hours == 12 && minutes >= 30) || (hours > 12 && hours < 15) {
ContentView2()
} else if (hours >= 15 && hours < 18) || (hours == 18 && minutes < 30) {
ContentView3()
} else {
ContentView1()
}

But I prefer using an other method: convert your values pair into a single value - in this case to day minutes, and use this value in switch: in this case you can use ranges which looks more readable to me:

var body: some View {
switch hoursAndMinutesToMinutes(hours: dateComps.hour!, minutes: dateComps.minute!) {
case hoursAndMinutesToMinutes(hours: 12, minutes: 30)...hoursAndMinutesToMinutes(hours: 14, minutes: 59):
ContentView2()
case hoursAndMinutesToMinutes(hours: 15, minutes: 00)...hoursAndMinutesToMinutes(hours: 18, minutes: 30):
ContentView3()
default:
ContentView1()
}
}

func hoursAndMinutesToMinutes(hours: Int, minutes: Int) -> Int {
hours * 60 + minutes
}

How can I set countDownTimer mode in DatePicker on SwiftUI?

The only way to get the countdown behavior right now is by wrapping UIDatePicker in a custom view.

Here is a simplified version of Ailton Vieira Pinto Filho's code using countDownDuration.

import SwiftUI

struct DurationPicker: UIViewRepresentable {
@Binding var duration: TimeInterval

func makeUIView(context: Context) -> UIDatePicker {
let datePicker = UIDatePicker()
datePicker.datePickerMode = .countDownTimer
datePicker.addTarget(context.coordinator, action: #selector(Coordinator.updateDuration), for: .valueChanged)
return datePicker
}

func updateUIView(_ datePicker: UIDatePicker, context: Context) {
datePicker.countDownDuration = duration
}

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

class Coordinator: NSObject {
let parent: DurationPicker

init(_ parent: DurationPicker) {
self.parent = parent
}

@objc func updateDuration(datePicker: UIDatePicker) {
parent.duration = datePicker.countDownDuration
}
}
}

UIDatePicker with 5 min interval get date on appear with interval

you could check the date and round it to your needs like this:

override func viewDidLoad() {
super.viewDidLoad()

let calendar = Calendar.current
var dateComponents = calendar.dateComponents([.month, .day, .year, .hour, .minute], from: datePicker.date)
guard var hour = dateComponents.hour, var minute = dateComponents.minute else {
print("something went wrong")
return
}

let intervalRemainder = minute % datePicker.minuteInterval
if intervalRemainder > 0 {
// need to correct the date
minute += datePicker.minuteInterval - intervalRemainder
if minute >= 60 {
hour += 1
minute -= 60
}

// update datecomponents
dateComponents.hour = hour
dateComponents.minute = minute

// get the corrected date
guard let roundedDate = calendar.date(from: dateComponents) else {
print("something went wrong")
return
}

// update the datepicker
datePicker.date = roundedDate
}
}

feel free to ask if anything is unclear!



Related Topics



Leave a reply



Submit