My timers shouldn’t be clickable when the minute is done - ios

I’m using time pickers and they work correctly as expected but the problem that i dont want to user to reserve a past time. when i click on the time pickers they doesn’t allow me to reserve past time but the problem is when i leave it opened and time continues it allow me to choose past time which is the time i click on it for example i opened time picker at 10:11 when i leave time picker opened and its 10:12 it allow me to choose 10:11 which is in past. when 10:11 is done it shouldn’t be clickable. Hope its clear and this is my code if you can help
func createTimePicker() {
StartTimeTxt.textAlignment = .center
EndTimeTxt.textAlignment = .center
//tool bar
let toolbar = UIToolbar()
toolbar.sizeToFit()
//bar button(
let doneBtn = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePressed))
toolbar.setItems([doneBtn], animated: true)
//assign tool bar
StartTimeTxt.inputAccessoryView = toolbar
EndTimeTxt.inputAccessoryView = toolbar
// assign time picker to the txt field
StartTimeTxt.inputView = StartTimePicker
EndTimeTxt.inputView = EndTimePicker
let calendar = Calendar.current
//First range
let startTime = Date()
let startRangeEnd = calendar.date(byAdding: DateComponents(minute: 30), to: startTime)!
let startRange = startTime...startRangeEnd
//Second range
let endTime = calendar.date(byAdding: DateComponents(minute: 1), to: startRangeEnd)!
let endRangeEnd = calendar.startOfDay(for: calendar.date(byAdding: DateComponents(day: 1), to: startTime)!)
let endRange = endTime...endRangeEnd
StartTimePicker.date = startTime
StartTimePicker.minimumDate = startTime
StartTimePicker.maximumDate = startRangeEnd
EndTimePicker.date = endTime
EndTimePicker.minimumDate = endTime
EndTimePicker.maximumDate = endRangeEnd
if #available(iOS 13.4, *) {
StartTimePicker.preferredDatePickerStyle = .wheels
EndTimePicker.preferredDatePickerStyle = .wheels
}
} ```

Related

Forcing user not to put previous time on time pickers

I’m using time pickers and they work correctly as expected but the problem that i dont want to user to reserve a past time. when i click on the time pickers they doesn’t allow me to reserve past time but the problem is when i leave it opened and time continues it allow me to choose past time which is the time i click on it for example i opened time picker at 10:11 when i leave time picker opened and its 10:12 it allow me to choose 10:11 which is in past. im planning to show an error massage and force the time pickers to set time at current time if user chooses start time < current time. Hope its clear and this is my code if you can help
func createTimePicker() {
StartTimeTxt.textAlignment = .center
EndTimeTxt.textAlignment = .center
//tool bar
let toolbar = UIToolbar()
toolbar.sizeToFit()
//bar button(
let doneBtn = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePressed))
toolbar.setItems([doneBtn], animated: true)
//assign tool bar
StartTimeTxt.inputAccessoryView = toolbar
EndTimeTxt.inputAccessoryView = toolbar
// assign time picker to the txt field
StartTimeTxt.inputView = StartTimePicker
EndTimeTxt.inputView = EndTimePicker
let calendar = Calendar.current
//First range
let startTime = Date()
let startRangeEnd = calendar.date(byAdding: DateComponents(minute: 30), to: startTime)!
let startRange = startTime...startRangeEnd
//Second range
let endTime = calendar.date(byAdding: DateComponents(minute: 1), to: startRangeEnd)!
let endRangeEnd = calendar.startOfDay(for: calendar.date(byAdding: DateComponents(day: 1), to: startTime)!)
let endRange = endTime...endRangeEnd
StartTimePicker.date = startTime
StartTimePicker.minimumDate = startTime
StartTimePicker.maximumDate = startRangeEnd
EndTimePicker.date = endTime
EndTimePicker.minimumDate = endTime
EndTimePicker.maximumDate = endRangeEnd
if #available(iOS 13.4, *) {
StartTimePicker.preferredDatePickerStyle = .wheels
EndTimePicker.preferredDatePickerStyle = .wheels
}
}
#objc func donePressed(){
// formatter
let calendar = Calendar.current
let startTime = Date()
let startRangeEnd = calendar.date(byAdding: DateComponents(minute: 30), to: startTime)!
let startRange = startTime...startRangeEnd
//Second range
let endTime = calendar.date(byAdding: DateComponents(minute: 1), to: startRangeEnd)!
let endRangeEnd = calendar.startOfDay(for: calendar.date(byAdding: DateComponents(day: 1), to: startTime)!)
let endRange = endTime...endRangeEnd
let formatter = DateFormatter()
formatter.dateStyle = .none
formatter.timeStyle = .short
StartTimeTxt.text = formatter.string(from: StartTimePicker.date)
self.view.endEditing(true)
EndTimeTxt.text = formatter.string(from: EndTimePicker.date)
self.view.endEditing(true)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "h:mm a"
startTimer = formatter.string(from: StartTimePicker.date)
endTimer = formatter.string(from: EndTimePicker.date)
// print(start, end)
// Format and print in 12h format
let hourAndMinutes = Calendar.current.dateComponents([.hour, .minute], from: StartTimePicker.date, to: EndTimePicker.date)
print(hourAndMinutes)
// Calculate price, the formula is just an example
var minutesPrice = 0
if ( hourAndMinutes.minute! == 0 ){
minutesPrice = 0
}
else {
minutesPrice = 15
}
let price = hourAndMinutes.hour! * 15 + minutesPrice
TotalPrice.text = String(price) + "SAR"
} ```

Storing value of UITextField

I'm using time pickers and I want to store the two values to use them in calculating price, store in firebase.
This is my UI to simplify the idea
The problem is that i don't know which part I can use to store the value of start time and end time (the numbers in UI are written in arabic)
This is my code, can you guide me to the way to store the UITextField values?
#IBOutlet weak var StartTimeTxt: UITextField!
#IBOutlet weak var EndTimeTxt: UITextField!
func createTimePicker() {
StartTimeTxt.textAlignment = .center
EndTimeTxt.textAlignment = .center
//tool bar
let toolbar = UIToolbar()
toolbar.sizeToFit()
//bar button(
let doneBtn = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePressed))
toolbar.setItems([doneBtn], animated: true)
//assign tool bar
StartTimeTxt.inputAccessoryView = toolbar
EndTimeTxt.inputAccessoryView = toolbar
// assign time picker to the txt field
StartTimeTxt.inputView = StartTimePicker
EndTimeTxt.inputView = EndTimePicker
//time picker mode
/* StartTimePicker.datePickerMode = .time
EndTimePicker.datePickerMode = .time*/
let calendar = Calendar.current
//First range
let startTime = Date()
let startRangeEnd = calendar.date(byAdding: DateComponents(minute: 30), to: startTime)!
let startRange = startTime...startRangeEnd
//Second range
let endTime = calendar.date(byAdding: DateComponents(minute: 1), to: startRangeEnd)!
let endRangeEnd = calendar.startOfDay(for: calendar.date(byAdding: DateComponents(day: 1), to: startTime)!)
let endRange = endTime...endRangeEnd
StartTimePicker.date = startTime
StartTimePicker.minimumDate = startTime
StartTimePicker.maximumDate = startRangeEnd
EndTimePicker.date = endTime
EndTimePicker.minimumDate = endTime
EndTimePicker.maximumDate = endRangeEnd
if #available(iOS 13.4, *) {
StartTimePicker.preferredDatePickerStyle = .wheels
EndTimePicker.preferredDatePickerStyle = .wheels
}
}

How to call function at 8:30am every day

Im trying to make a quiz app and I want it to show a new question every day at 8:30am and disappear at 6pm. I have seen online that the main way is to use timer but my question is if the person changes time zones, won't the timer be out of sync? Or does it restart every day? here is my code: (please note I am a beginner)
Also, whenever I load my app, the question appears for a second and then disappears and then appears again after the timer is up.
#objc func loadQuestion() {
questionView.alpha = 0
self.view.addSubview(questionView)
questionView.center = self.view.center
questionView.transform = CGAffineTransform.init(scaleX: 1.3, y: 1.3)
UIView.animate(withDuration: 0.4) {
self.visualEffectView.effect = self.effect
self.questionView.alpha = 1
self.questionView.transform = CGAffineTransform.identity
let date = Date().addingTimeInterval(30600)
let timer = Timer(fireAt: date, interval: 0, target: self, selector: #selector(self.loadQuestion), userInfo: nil, repeats: false)
RunLoop.main.add(timer, forMode: .common)
}
}
#objc func loadOutQuestion() {
UIView.animate(withDuration: 0.3, animations: {
self.questionView.transform = CGAffineTransform.init(scaleX: 1.3, y: 1.3)
self.questionView.alpha = 0
self.visualEffectView.effect = nil
let date = Date().addingTimeInterval(64800)
let timer = Timer(fireAt: date, interval: 0, target: self, selector: #selector(self.loadOutQuestion), userInfo: nil, repeats: false)
RunLoop.main.add(timer, forMode: .common)
}) { (succcess:Bool) in
self.questionView.removeFromSuperview()
}
}
You can use "Local Notification I put apple sample code please check it and you can modify sample code as per your requirement.
The steps for configuring a local notification are as follows:
Create and configure a UNMutableNotificationContent object with the notification details.
Create a UNCalendarNotificationTrigger, UNTimeIntervalNotificationTrigger, or UNLocationNotificationTrigger object to describe the conditions under which the notification is delivered.
Create a UNNotificationRequest object with the content and trigger information.
Call the addNotificationRequest:withCompletionHandler: method to schedule the notification; see Scheduling Local Notifications for Delivery
Official Document
Sample code
let content = UNMutableNotificationContent()
// Replace "Wake up!" with your "question title"
content.title = NSString.localizedUserNotificationString(forKey: "Wake up!", arguments: nil)
// Replace "Rise and shine! It's morning time!" with your "question description"
content.body = NSString.localizedUserNotificationString(forKey: "Rise and shine! It's morning time!",
arguments: nil)
// Configure the trigger for a 7am wakeup.
var dateInfo = DateComponents()
dateInfo.hour = 7
dateInfo.minute = 0
let trigger = UNCalendarNotificationTrigger(dateMatching: dateInfo, repeats: false)
// Create the request object.
let request = UNNotificationRequest(identifier: "MorningAlarm", content: content, trigger: trigger)
This is what I have so far. I don't know if Im getting closer or farther from resolving this issue
#objc func loadQuestion() {
self.view.addSubview(questionView)
questionView.center = self.view.center
questionView.transform = CGAffineTransform.init(scaleX: 1.3, y: 1.3)
questionView.alpha = 0
var dateComponents = DateComponents()
dateComponents.hour = 08
dateComponents.minute = 30
let currentTime = DateComponents()
let hour = currentTime.hour
let minute = currentTime.minute
var calendar = Calendar.current
calendar.timeZone = NSTimeZone.local
if hour >= dateComponents {
UIView.animate(withDuration: 0.4) {
self.visualEffectView.effect = self.effect
self.questionView.alpha = 1
self.questionView.transform = CGAffineTransform.identity
}
}
}
This will get 8:30am and 6:00pm from user's local time.
var calendar = Calendar.current
calendar.timeZone = NSTimeZone.local
let startDate = calendar.startOfDay(for: Date())
let EightAM = calendar.date(byAdding: .hour, value: 8, to: startDate)!
let EightThirtyAM = calendar.date(byAdding: .hour, value: 30, to: EightAM)!
let SixPM = calendar.date(byAdding: .hour, value: 18, to: startDate)!
If the App isn't open at these times, nothing will fire.
What you could do in this case is in ViewDidLoad, check
if Date() > EightThirtyAM && Date() < SixPM {
showQuiz()
} else {
hideQuiz()
}
If you want it to disappear at 6:00pm on the dot add
let timer = Timer(fireAt: SixPM, interval: 0, target: self, selector: #selector(hideQuiz), userInfo: nil, repeats: false)
RunLoop.main.add(timer, forMode: .common)
If you prefer a component solution try.
var calendar = Calendar.current
calendar.timeZone = NSTimeZone.local
let hours = calendar.component(.hour, from: Date())
let minutes = calendar.component(.minute, from: Date())
let timeFloat:Float = Float(hours) + Float(minutes)/60
if timeFloat > 8.5 && timeFloat < 18 {
showQuiz
} else {
hideQuiz
}

How to set a default date value in a inputView

I would like to set a default date value in inputView.
I have:
func createDatePickerDgeb1() {
datePickergeb.datePickerMode = .date
let toolbar = UIToolbar()
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePressedgeb1))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
toolbar.setItems([spaceButton,doneButton], animated: false)
gebdatum.inputAccessoryView = toolbar
gebdatum.inputView = datePickergeb
}
The picker view shows me current date. Is possible that I can show for example the "01.01.1960" as a default?
// Create date components
var dateComponents = DateComponents()
dateComponents.year = 1960
dateComponents.month = 1
dateComponents.day = 1
// Create date from components
let userCalendar = Calendar.current // user calendar
let date = userCalendar.date(from: dateComponents)
// Set datePicker date
datePickergeb.setDate(date, animated: false)

Swift countdown timer labels for Days/Hours/Minutes/Seconds

I'm creating a countdown timer that counts down to an NSDate set in a UIDatePicker. I have a label that shows the date we're counting down to and that works fine.
What I'm also trying to add is labels for the number of whole days left and number of hours/minutes/seconds left in the current day (i.e. never more than 23/59/59) Here's what I've done at the minute but it obviously shows the values for the whole countdown. Hoping someone can help me work out the correct logic here.
let secondsLeft = sender.date.timeIntervalSinceDate(NSDate())
hoursLabel.text = String(secondsLeft % 3600)
minutesLabel.text = String((secondsLeft / 60) % 60)
secondsLabel.text = String(secondsLeft % 60)
I guess what I'm looking for is some swift equivalent of the datetime class you get in php
Got it - for Swift 2
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Day, .Hour, .Minute, .Second], fromDate: NSDate(), toDate: sender.date, options: [])
daysLabel.text = String(components.day)
hoursLabel.text = String(components.hour)
minutesLabel.text = String(components.minute)
secondsLabel.text = String(components.second)
Take a look at the NSCalendar class. Specifically look at the method
components:fromDate:toDate:options: That lets you take 2 dates and calculate the difference between them using whatever units you specify.
It's also localizable, so if you use the current calendar and the user uses the Chinese, Hebrew, or Arabic calendar then the calculations will give you results correct for that calendar.
Here's a Swift 4 version of Chris Byatt's answer that is also playground-friendly:
import UIKit
let calendar = Calendar.current
let now = Date()
let futureDate = Date.distantFuture
let components = calendar.dateComponents([.day, .hour, .minute, .second], from: now, to: futureDate)
let daysLabel = UILabel()
let hoursLabel = UILabel()
let minutesLabel = UILabel()
let secondsLabel = UILabel()
daysLabel.text = String(describing: components.day)
hoursLabel.text = String(describing: components.hour)
minutesLabel.text = String(describing: components.minute)
secondsLabel.text = String(describing: components.second)
print(components) // day: 723942 hour: 23 minute: 56 second: 0 isLeapMonth: false
// Bonus: here's an easy way to print grammatically correct labels based on numbers
if let seconds = components.second {
let labelText = "\(seconds) \(seconds == 1 ? "second" : "seconds")"
print(labelText) // 0 seconds, 1 second, 2 seconds, etc.
}
Only Copy and Paste this code :
#IBOutlet var countDownLabel: UILabel!
var count = 10800
override func viewDidLoad() {
super.viewDidLoad()
var timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(update), userInfo: nil, repeats: true)
}
func timeString(time: TimeInterval) -> String {
let hours = Int(time) / 3600
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format:"%02i:%02i:%02i", hours, minutes, seconds)
}
#objc func update() {
let time = timeString(time: TimeInterval(count))
count = count - 1
countDownLabel.text = time
}

Resources