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

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.

Related

Reset MinimumDate in iOS UIDatePicker

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

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

NSTimeIntervalSinceDate gives 86,399 seconds between consecutive days, why?

In iOS, Xcode9, and Obj-C, I am trying to find out how much time has elapsed in days between two dates. I know the NSTimeIntervalSince method yields a result in seconds. But it seems that when I calculate the seconds between consecutive days (like 11-2-2016 and 11-3-2016), I am 1 second short, yielding 86,399. If I calculate seconds between larger intervals, I am always a second short.
11-2-2016 to 11-4-2016: 172,799 (two 24-hour days but missing a second)
11-2-2016 to 11-5-2016: 259,199 (three 24-hour days but missing a second)
Here's my code:
#property (strong, nonatomic) NSDate *firstDate;
#property (strong, nonatomic) NSDate *secondDate;
#synthesize firstDate, secondDate;
int secondsIntervalFirstDatetoSecondDate = (fabs([firstDate timeIntervalSinceDate:secondDate]));
NSLog(#"seconds between firstDate and secondDate %i", secondsIntervalFirstDatetoSecondDate);
firstDate and secodDate are NSDate
They are entered by the user using a datePicker and date formatting is set as
[formatter setDateFormat:#"MM-dd-yyyy"];
I've searched for an answer but could find none.
First post for a newbie, sorry for any etiquette errors, I'll try to improve.
When you create a UIDatePicker and put it in "date" mode, the time is the time the date picker was created. If you're creating two pickers, they're going to be created at slightly different times. Even a very small difference in those times can lead to a 1-second difference.
You should never compute time-differences this way. There are not 86,400 seconds in a day. "How many days are between two points in time" is complicated, and you should use the tools designed for it: NSDateComponents and NSCalendar.
NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
NSInteger diffInDays = [[calendar components:NSCalendarUnitDay
fromDate:[calendar startOfDayForDate:date1]
toDate:[calendar startOfDayForDate:date2]
options:0] day];

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

uidatepicker 24hour formate in ios

I am Trying to assign the 24 hour formate to UIDATEPICKERVIEW but i have not exactly idea to implement it.
in my view.h file
#property(nonatomic,retain) IBOutlet UIDatePicker *picker_alarm;
in my view.m file
picker_alarm.date=[NSDate date];
in my .xib file
i have taken uidatepicker and its Mode Property to Time in viewcontroller.
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"NL"];
[picker_alarm setLocale:locale];
You can also use the storyboard to change time format to 24 hour.
Follow these steps:
go to storyboard
select you datePicker
select attributes inspector
Change "Locale" property to English(Europe)
and in your code use following snippet:
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setDateFormat:#"HH:mm"];
somelabel.text = [outputFormatter stringFromDate:_pickerDate.date];
You cannot force the date picker to show 24 hours time. That depends on the locale property
Doc says:
UIDatePickerModeTime, // Displays hour, minute, and optionally AM/PM designation depending on the locale setting (e.g. 6 | 53 | PM)
[datePicker setLocale:[NSLocale systemLocale]];
For testing this change the system time to 24hour mode. And check the picker in simulator
Create DatePicker with setting it custom Locale
let datePicker = UIDatePicker()
datePicker.datePickerMode = UIDatePickerMode.time
datePicker.locale = Locale.init(identifier: "NL") //or: Locale.init(identifier:en_GB") // using Great Britain
Grab the time from above DatePicker,
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
lblTime.text = dateFormatter.string(from: sender.date)

Resources