UIDatePicker date method is picking wrong date: iPhone Dev - iphone

I am getting very strange behaviour on UIDatePicker. I have a view with date picker declared in .h file as IBOutlet UIDatePicker *datePicker; with property nonatomic and retain. datePicker is properly linked in IB file.
In the code I am setting the minimum, maximum, initial date and action to call for UICOntrolEventValueChanged using following code
If (!currentDate) {
initialDate = [NSDate date];
} else {
initialDate = currentdate;
}
[datePicker setMinimumDate:[NSDate date]];
[datePicker setMaximumDate:[[NSDate date] addTimeInterval:5 * 365.25 * 24 * 60 * 60]]; // to get upto 5 years
[datePicker setDate:initialDate animated:YES];
[datePicker addTarget:self action:#selector(getDatePickerValue:) forControlEvents:UIControlEventValueChanged];
In getDatePickerValue, I get the new date using datePicker.date.
When the view is closed (using a done button), I get the current value of the date using datePicker.date.
Now if the view is called with no 'currentDate', the picker returns 'todays date'. This is what happens the 'first' time my pickerView is called. Each subsequent call to the view, with no 'current date' gives me a different and later date from today. So,
first time I get today's date say 9 Jun 2010
second time datePicker.date returns 10 Jun 2010
third time 11 Jun 2010 and so on. Though its not always incremental, but mostly it is.
I have put NSLogs, and verified the initial date is set correctly.
The problem is only on the device (on OS 3.0), the issue is not replicated on simulator.
I can't find what I have done wrong. I hope somebody else has come across similar problem and can help me resolve this.

The issue is finally solved. Listing what resolved the problem for me, so if someone else encounters similar issue they can try these steps
I did two things
1. set the locale and calendar of the datePicker -
NSLocale *locale = [NSLocale currentLocale];
[dateFormatter setLocale:locale];
self.datePicker.locale = locale;
self.datePicker.calendar = [locale objectForKey:NSLocaleCalendar];
But this alone did not solve the problem.
2. I put 'self' before each reference to datePicker i.e. replaced all datePicker with self.datePicker. This must have forced the compiler setters and getters to be called.
I do not understand fully on why not using 'self' caused it to behave so strangely. But yes , I will be more careful with using the correct setters for my variables.
Thank you for taking time looking at my problem.

IBOUTLET UIDatePicker *datePicker;
IBOUTLET UILabel *label;
}
-(void)click:(id)sender;
- (void)viewDidLoad {
[super viewDidLoad];
NSDate *dateFromPicker = [[NSDate alloc]init];
[date setDate:dat animated:YES];
}
-(void)click:(id)sender {
NSDate *selectDate = [datePicker date];
NSString *dateString = [NSString stringWithFormat:#"%#",selectDate];
[label setText:dateString];
}
this will work,

Related

Upper and lower limit on UIDatePicker

So a few weeks ago I asked for a tip on how to actually lock a specific range of dates on UIDatePicker, instead of just graying them. It worked fine.
But now I've reached a similar situation, and can't get it to work. Now I have a minimum AND a maximum date, i.e., I only want to allow a small (or not) interval of dates.
Here's what I'm trying to do: (I added a target on the datepicker)
-(void) disableDate {
if ([datePicker.date compare:[NSDate date]] == NSOrderedDescending || [datePicker.date compare:datePicker.minimumDate] == NSOrderedAscending) {
datePicker.date = [NSDate date];
[datePicker reloadInputViews];
}
}
Some notes:
1) It's working only for the first time I change datepicker's date. The second time (and on) it just doesn't work anymore - datepicker won't scroll back to current date.
2) Note 1) is happening for some reason I don't know, cause disableDate is being called, BUT the app NEVER goes into the "if", like the conditions I set are never being satisfied.
In other words: I don't know why it's scrolling once since it never goes into the if statement, and I also don't know WHY it never goes into the if statement!
Any ideas here?
Thanks in advance!
EDIT: The minimum.date and maximum.date are set.
Well, if you like the user don't be able to select dates without your range, use this:
UIDatePicker *datePicker = [[UIDatePicker alloc] init];
datePicker.datePickerMode = UIDatePickerModeDate;
datePicker.minimumDate=_minDate;
datePicker.maximumDate=_maxDate;
Where _minDate and _maxDate are defined:
NSDateComponents* components=[[NSDateComponents alloc] init];
[components setYear:1900];
_minDate=[[NSCalendar currentCalendar] dateFromComponents:components];
_maxDate=[NSDate date];
And bingo, the limits are defined.
I hope this help you.
Ok, so I finally solved it. I'll post here how I did it in case someone else struggles with this weird datepickers behaviour.
So, what's happening here is that the maximum date and minimum date properties also lock the date within your limit range. But they do that without updating the datepicker view. Plus, the datepicker does that before its value actually change so when your app reaches the if inside the disableDate method, its date is already set back to current date (or nearest date or something like that - but a valid date) and the if will be skipped.
To solve that I thought of using setDate:animated: in a redundant way, like:
[myDatePicker setDate:myDatePicker.date animated: YES]
But then the datepicker wouldn't do anything, so I created a NSDate with datepicker.date plus 1 second, and then set the new date. In other words:
- (void) disableDate {
NSDate * oneSecondAfterPickersDate = [datePicker.date dateByAddingTimeInterval:1] ;
if ( [datePicker.date compare:datePicker.minimumDate] == NSOrderedSame ) {
datePicker.date = oneSecondAfterPickersDate ;
}
else if ( [datePicker.date compare:datePicker.maximumDate] == NSOrderedSame ) {
datePicker.date = oneSecondAfterPickersDate ;
}
}
Hope it helps someone :)
EDIT: forgot to mention -> I'm using UIControlEventValueChanged to trigger the method.

UIDatePicker issue on second instance

I am using two UIDatepicker in my project.
When I create second DatePicker, then I face problem in setting date on the second.
This is archive of my project with two DatePickers.
Where is problem?
You don't have the outlet connected in the ContactCardView.xib file. So effectively your datePickerBD is nil.
I found interesting bug in an UIDatePicker in line with setTimeZone in FirstViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
datePicker.locale = [NSLocale currentLocale];
[datePicker setDatePickerMode: UIDatePickerModeDate];
[datePicker setTimeZone: [NSTimeZone timeZoneWithAbbreviation:#"GMT"]]; // This line make strange effect on DatePicker with create second instance one
}
If delete last operator, bug disappear!

Can't Select today's date on uidatepicker ( already pre-selected)

I added a UIDatePicker in my IOS app which get loaded by default with today's date selected.
I'm listening to the selected event to update my field but as today's is already selected I never get it today is the date I want to selec( because it is already selected). I need to change at least one of the column to soemthing different , and in a second step select back today's date.
Anyway to display the datepicker without a selected day or somehow listeng to the tab on the picker instead of the selection ?
Wouldn't like to add a Todays button in the toolbar on adding any external control to solve this, or start with a different day pre-selected as it iwll be the same issue with the pre-selected date.
Thanks
I am not 100% sure whether you are looking for this or not. But this works fine for me.
in the viewcontroller.m
- (void)viewDidLoad
{
[super viewDidLoad];
dp.date = [NSDate date]; //dp is datepicker object
NSDateFormatter *formDay = [[NSDateFormatter alloc] init];
[formDay setDateFormat:#"dd/MM/yyy HH:mm"];
NSString *day = [formDay stringFromDate:[dp date]];
txt.text = day;
}
-(IBAction)datepick:(id)sender
{
NSDateFormatter *formDay = [[NSDateFormatter alloc] init];
[formDay setDateFormat:#"dd/MM/yyy HH:mm"];
NSString *day = [formDay stringFromDate:[dp date]];
txt.text = day;
}
connect the method to value changed event of date picker and include UITextFieldDelegate
when the view is loaded,
when the date picker is rolled
Apple did not implement any notifications for this. The reason being is that the user will tap, spin, and change the date picker until they find the date they want. Then they would hit some sort of done or next button. You would not want the user to be trying to select a date and the picker keep dismissing. If you really want to implement this then you can subclass UIDatePicker or and capture touches on the section you want.
Try subclassing UIDatePicker, & overriding hitTest:withEvent:
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
// intercept the user touching the initially presented date on a datePicker,
// as this will normally not send an event.
// here we check if the user has touched the middle section of the picker,
// then send the UIControlEventValueChanged action
CGFloat midY = CGRectGetMidY(self.bounds);
CGFloat dY = fabs(midY - point.y);
if (dY < 17.0) // the active section is around 36px high
{
NSSet *targets = self.allTargets;
for (id target in targets)
{
NSArray *actions = [self actionsForTarget:target forControlEvent:UIControlEventValueChanged];
for (NSString *action in actions)
{
// suppress the leak warning here as we're not returning anything anyway
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[target performSelector:NSSelectorFromString(action) withObject:self];
}
}
}
return [super hitTest:point withEvent:event];
}
I'm sure it could be improved, but as a starting point it might help you.

Disabling a particular date in uidatepicker in objective c

Is there any way to disable a particular date in uidatepicker ?
Since there is not direct method to implement this, what you can do is get the "UIControlEventValueChanged" from datePicker like
UIDatePicker * datePick = [[UIDatePicker alloc] init];
[datePick addTarget:self action:#selector(disableDate) forControlEvents:UIControlEventValueChanged];
In disableDate method, the user can check if the current date is equal to the disableDate.If yes, then he can set the currentDate to some previous date.
-(void)disableDate{
NSDate *pickedDate = datePicker.date; // Get current Date
NSDate *disabledDate = [self getDisabledDate] // Returns Disabled Date.(getDisabledDate returns a date to be diabled).
if([pickedDate compare:disabledDate] == NSOrderedSame){
[datePick setDate:[self someOtherDate] animated:YES];
// Set current Date to some other date(someOtherDate methos returns a date to be set ,if disabled date is selected).
}

How do i take a date out of a datepicker and then put it back in again?

I've tried numerous ways to do this but i can't seem to get it to work. So here's more precisely what i want - you press a button, it takes the date and time set in the datepicker and stores it (in an NSDate most likely, although i have tried converting it back and forth between that and an NSString - didn't work). Then you press another button and it puts the date and time stored and sets the datepicker as that date and time.
Suggestions on how I could do this?
#property (retain) NSDate *savedDate;
#property (retain) IBOutlet UIDatePicker *datePicker;
// To save the date:
self.savedDate = datePicker.date;
// To put it back into the picker:
datePicker.date = self.savedDate;
You actually process Date picker changes as they are made, register the UIControlEventValue changed with a method on your class via the selector paradigm:
[dateSelector addTarget:self
action:#selector(processDateSelection:)
forControlEvents:UIControlEventValueChanged];
Then in that method process the time on the picker in that method (mine writes it bac to a UITextField:
control.text = [NSString stringWithFormat:#"%#", [df stringFromDate: dateSelector.date]];
To set the date in the picker, use an NSDate object (With a dateFormatter):
[df setDateFormat:#"yyyy-MM-dd"];
NSDate *defaultDate = [df dateFromString: textField.text];
dateSelector.date = defaultDate;
You will also need at method to dismiss your date picker as there is no logical "end" like in a standard Picker. I just bound a method to button, set it as the UIAccessoryView on the Date picker, and that putton tap dismissed the picker.