Upper and lower limit on UIDatePicker - iphone

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.

Related

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

Slider with real time in Label

I need a slider for displaying real time in slider-label from 12-00 AM to 11-45 PM with step size 15 minutes. But I just have no idea how to do it. Сan anybody give some suggestions to me?
If you just need a time chooser with slider, use the following code in the sliderChanged: handler:
- (IBAction)onSliderChange:(id)sender {
UISlider *slider = (UISlider *)sender;
NSUInteger numberOfSlots = 24*4 - 1; //total number of 15mins slots
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"h-mm a"];
NSDate *zeroDate = [dateFormatter dateFromString:#"12-00 AM"];
NSUInteger actualSlot = roundf(numberOfSlots*slider.value);
NSTimeInterval slotInterval = actualSlot * 15 * 60;
NSDate *slotDate = [NSDate dateWithTimeInterval:slotInterval sinceDate:zeroDate];
[dateFormatter setDateFormat:#"h-mm a"];
self.timeLabel.text = [dateFormatter stringFromDate:slotDate];
}
Create a slider, and in the view controller, have the slider change the label as the value on the slider changed. To set the range of values, change the range in the Storyboard under the properties (you can set the change interval to steps of 15 there too). You may want to give it the interval in minutes or something similar and then just convert that to time :)
- (IBAction)sliderChanged:(UISlider *)sender
I'm adding another answer to add code. Yes, you can get the value from the slider and then set the text of the label after converting the value to a time. Like so:
// Add 0.5 to slider value and truncate it to an integer by type casting it as integer
int sliderIntValue = (int)([sender value] + 0.5f);
//do some conversion and set the label to the value
self.sliderLabel.text = newLabelText;
You may use NSTimer to call a method every 15 minutes and update the slider/label with the current time.
You may want to take a look at NSDateFormatter, it may be useful to obtain proper string representation for your date.

Incrementing a UILabel in Objective-C

So essentially I want the UILabel to increment every time a button is clicked. I currently have something like this:
- (IBAction) incrementCount {
[buttonCounter = buttonCounter++]; // Increment by 1.
}
I declare button counter to be an int in the header file. Is that the right way of doing it? Furthemore, upon click, i'd like a time stamp printed as well. Is there a built-in function for fetching a time stamp? Thanks.
use:
- (IBAction) incrementCount {
buttonCounter++;
yourUILabel.textLabel.text = [NSString stringWithFormat:#"%i", buttonCounter];
}
You can get a current date and time using
[NSDate date]
To get timestamp, use
[[NSDate date] timeIntervalSince1970] * 1000;
This
[buttonCounter = buttonCounter++];
is equivalent to
[buttonCounter = buttonCounter+1];
[buttonCounter = buttonCounter];
Therefore you can change your code to
buttonCounter++;
For the timestamp you could use [NSDate date]; and a NSDateFormatter for the display.

UIDatePicker date method is picking wrong date: iPhone Dev

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,