Reset MinimumDate in iOS UIDatePicker - ios

I have 2 UIDatePickers, one set in UIDatePickerModeDate and the other in UIDatePickerModeTime.
If the first one has its date set to today, then the second one must have a restriction such that the user cannot select a time that is before now. To do this I use the setMinimumDate function. However, if the user sets a date in the future, I need to reset the minimumDate property, meaning that there should be no minimumDate set on the picker.
I am able to achieve this by calling
[self.timePicker setMinimumDate:nil];
But this gives me an exception in the Xcode console output as below.
-[__NSCFCalendar components:fromDate:]: date cannot be nil
Future exception.
A few of these errors are going to be reported with this complaint, then further violations will simply be ignored.
How can I remove the minimumDate property of my timePicker after it has been set, without this exception being raised?
Thank you.
EDIT:
The reason I tried setting it to nil was because Apple's documentation says that the default value of the minimumDate property is nil (here).
Also, I did try to set the minimum date to the future date selected by the user, after making the time component zero. This causes the time to be selected as 12 AM in the picker which is acceptable. Now if the user selects today's date again, nothing happens when I set the minimumDate property, i.e. I cannot toggle the minimumDate using this. The code is as follows:
(void)setMinimumDateForTimePicker {
if([[NSCalendar currentCalendar] isDateInToday:self.datePicker.date]) {
NSLog(#"Min date for today");
[self.timePicker setMinimumDate:[self roundUpToNearestFifteenMinutes:[NSDate date]]];
} else {
// date is in the future so zero out time
NSLog(#"Min date for the future");
NSDateComponents* selectedDateWithZeroTime = [[NSCalendar currentCalendar] components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:self.datePicker.date];
[self.timePicker setMinimumDate:[[NSCalendar currentCalendar] dateFromComponents:selectedDateWithZeroTime]];
}
[self updateStartTimeField:nil];
}

This is the code that worked finally for what I was trying to do.
- (void)setMinimumDateForTimePicker {
if([[NSCalendar currentCalendar] isDateInToday:self.datePicker.date]) {
[self.timePicker setMinimumDate:[self roundUpToNearestFifteenMinutes:[NSDate date]]];
} else {
[self.timePicker setMinimumDate:[[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]];
}
[self updateStartTimeField:nil];
}

Related

UIDatePicker: While selecting date, it jumps to any random date

I have been trying to fix this issue since so long but did not find any way to sort this out.
When I'm trying to select a year sometimes the year component of the date picker jumps to a random year. (The same thing happens with date and month selection)
The data picker is contained in a UIView and I have created an IBOutlet for it.
- (void)setupforBirthdates {
[self.dtPicker setDatePickerMode: UIDatePickerModeDate];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier: NSCalendarIdentifierGregorian];
NSDate *currentDate = [NSDate date];
NSDateComponents * comps = [[NSDateComponents alloc] init];
[comps setYear: -17];
NSDate * maxDate = [gregorian dateByAddingComponents: comps toDate: currentDate options: NSCalendarMatchStrictly];
[comps setYear: -50];
NSDate * minDate = [gregorian dateByAddingComponents: comps toDate: currentDate options: NSCalendarMatchStrictly];
[self.dtPicker setMinimumDate:minDate];
[self.dtPicker setMaximumDate:maxDate];
[self.dtPicker setDate:maxDate];
}
ISSUE See the below image...
I thought that it may be due to some 3rd party libraries this is happening. I have the following pod in my project
pod 'AFNetworking'
pod 'GoogleMaps'
pod 'GooglePlaces'
pod 'Fabric'
pod 'Crashlytics'
pod 'RACollectionViewReorderableTripletLayout'
pod 'FBSDKLoginKit'
pod 'Socket.IO-Client-Swift', '~> 13.3.0'
How can I solve this issue?
Any help/suggestions?
UPDATE
I what to restrict user to select birth year from 17 to 50 year only so the minDate will be 17 years back from current year
maxDate will be 50 years back from the current year
The issue is also coming if I don't set minDate and maxDate
Tested the following case too
I just drag and drop new date picker on screen. I did not set any min/max date, nor connect an IBOutlet and I run app and when I scroll to any date the same issue is coming
You will be surprised that I have created a custom date picker using UIPickerView and the issue is still there.
When I have created a new demo project and copy pasted the code in demo project then this issue is not coming. I've tested it many times on demo project the issue is not coming.
The following func. is called when I change the date in date picker.
- (IBAction)datePickerValueChanged:(id)sender {
NSDateFormatter *dateFormat=[[NSDateFormatter alloc]init];
[dateFormat setDateFormat:#"yyyy-MM-dd"];
self.txtBirthday.text = [NSString stringWithFormat:#"%#",[dateFormat stringFromDate:self.dtPicker.date]];
}
The strange thing is that for the When I just put(drag & drop) UIDatePicker View on a screen just to test its scrolling issue. When I scroll date time picker view then also it was scrolling at random location.
I feel that it is the issue with third party library.
After many hours of debugging and trail-run, I finally found the third party library which was the source of this issue.
Actually is was the category name is UITableView+SPXRevealAdditions.
When I removed it UIDatePicker is working fine and when I re-added the issue is started occurring.
It is really very strange but It worked for me.:D
Update:
I wanted the that 3rd party too. So what I did id added a dummy pan gesture in viewDidLoadMethod:.
UIPanGestureRecognizer *p = [[UIPanGestureRecognizer alloc] initWithTarget:nil action:#selector(doNothing)];
[self.dtPicker addGestureRecognizer:p];
and the dummy method.
- (void)doNothing {
printf("do nothing");
}
This solved my problem and Now the UIDatePicker is working fine and also third party library too...cheers...:D.
You can check whenever your picker want to change the label value by comparing it with the min and max date, here the code *please swap the Ascending and descending if my code do wrong
- (IBAction)datePickerValueChanged:(id)sender {
NSDateFormatter *dateFormat=[[NSDateFormatter alloc]init]; [dateFormat setDateFormat:#"yyyy-MM-dd"];
NSDate * maxDate = [gregorian dateByAddingComponents: comps toDate: currentDate options: NSCalendarMatchStrictly];
[comps setYear: -50];
NSDate * minDate = [gregorian dateByAddingComponents: comps toDate: currentDate options: NSCalendarMatchStrictly];
NSDate * curDate = self.dtPicker.date;
if(([curDate compare:minDate] == NSOrderedAscending)&& ([curDate compare:maxDate] == NSOrderedDescending)){
self.txtBirthday.text = [NSString stringWithFormat:#"%#",[dateFormat stringFromDate:self.dtPicker.date]];
}
}
class ViewController: UIViewController {
#IBOutlet weak var datePicker: UIDatePicker!
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.configureDatePicker()
}
private func configureDatePicker() {
let calendar = Calendar(identifier: .gregorian)
// 17 years less
let minimumDate = calendar.date(byAdding: .year, value: -17, to: Date())
// 50 years max. 17 + 33 = 50
let maximumDate = calendar.date(byAdding: .year, value: -50, to: Date())
self.datePicker.minimumDate = minimumDate
self.datePicker.maximumDate = maximumDate
}
#IBAction func onDatePickerChanged(sender: UIDatePicker) {
let dateFormtter = DateFormatter()
dateFormtter.dateStyle = .medium
self.label.text = dateFormtter.string(from: sender.date)
}
}
This code works fine without any issue. I think you have some issue in your code. UIDatePicker is resetting in some places.

How to set calendar type to Gregorian when app launch?

Does anyone know how to set calendar type to Gregorian when the app is launch? Most of users of the app that I created use Buddhist calendar, but I want to change it to Gregorian so Datepicker in the app use Gregorian.
Here is the code that I put in app delegate.
if (self.gregorian == nil) {
NSCalendar* temc = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
self.gregorian = temc;
}
You simply need to set the calendar property of your date picker.
Something like:
self.datePicker.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
or, if you have set your property,
self.datePicker.calendar = self.gregorian
There is no way to change the "default" calendar for your app so that date pickers implicitly use the Gregorian calendar.
Set your datePicker's calendar to gregorian type.
datePicker.calendar = Calendar(identifier: .gregorian)
date picker by default is Gregorian
var datePicker = UIDatePicker()
datePicker.calender = .gregorian

UICollectionView is not scrolling to position

I have a UICollectionView in a static UITableView. I'm trying to make the collectionView scroll to an indexPath in viewDidLoad. It's not scrolling to position on startup, when I select an indexPath it scrolls to that position. I made a clean project that produces the problem.
I thought the simplest way to do this was instead of making you to try and recreate the problem, I would just upload it. So here it is: Project with problem
There are only two small problems:
1.The selectedDate does not match with your dates array. Compare the two date in the following image:
2.You should update UI in viewDidAppear as #Omar Al-Shammary said.
The Solution:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:[NSDate date]];
[self setSelectedDate:[calendar dateFromComponents:components]];
}

Can I make a button do an NSDate comparison in iOS?

Is it possible to have an action from a button a) do an NSDate store when tapped, and then b) for that method to do a date comparison with an if statement?
So, for instance, if the stored NSDate was less than 12 hours ago, the user could not press the button again?
Haven't come across a tip on this from my research.
Sure. You can get current date by code
[NSDate date]
Then save him into NSUserDefaults
And check a current date with saved date on button press.
How
if ( [[NSDate date] timeIntervalSinceDate: savedDate] >= 12*60*60) // 12 hours
{
// do your steps
}

NSDate crash with successive actions

I have the following code below that is meant to change a class var called "today" forward or backward by one day. It will work one time but then after that it crashes. It will do the same no matter if I press the left button or right button. What am I doing wrong?
the var today is a class var initiated as .. today = [NSDate date]
Here is the method that crashes:
(IBAction)changeDateByOne:(id)sender{
NSDate *newDay;
NSDate *currentDay = today;
NSTimeInterval secondsPerDay = 24 * 60 * 60;
if(sender == leftButton){
newDay = [currentDay addTimeInterval:-secondsPerDay];
}else if(sender == rightButton) {
newDay = [currentDay addTimeInterval: secondsPerDay];
}
today = newDay;
}
Not only do you need to retain the date created, but you also need to release the existing value held by "today," otherwise you'll leak the old reference.
When initializing the instance, use:
today = [[NSDate date] retain];
I would change the last line to:
[today release];
today = [newDay retain];
And finally, in your dealloc method, add:
[today release];
before calling [super dealloc];
You need to read the memory management documentation. That’s here:
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
If you’re adding or subtracting days, you might want to read this which is an alternative way of doing the same thing:
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/DatesAndTimes/Articles/dtCalendricalCalculations.html#//apple_ref/doc/uid/TP40007836-SW1
Lastly, if something crashes, it’s often helpful to look at the back traces (and include them in your questions if you can’t figure it out for yourself). Memory management bugs are usually the problem if you see objc_msgSend (or one of its companions) in the trace.
Maybe you need to say
today = [[NSDate date] retain]
I think you need to retain the newDay object returned from the addTimeInterval method. You may also need to release today before you do the assignment at the end.

Resources