I have been trying to use UILocalNotification and setting timezone to some other timezone than my default.
The purpose is to do something like:
-User will schedule an alert with time and timezone
-Show alert when that timezone becomes specified time.
In more verbal description, let say I live in LosAngeles and my gf is in Chicago. I want to set up an alert when chicago is 7am, for weekdays.
For one alert, I can do without timezone, to do absolute time. But I want to allow users to set repeat flags, in which case I can't seem to do - I tried setting localnotification's timezone property to chicago as above example, however the local notification will not fire.
I logged the uinocalnotification during serialization process, and here's one output:
"<UIConcreteLocalNotification: 0xfb25a50>{fire date = 2011-02-06 06:02:00 -0800, time zone = America/Chicago (CST) offset -21600, repeat interval = 16, next fire date = 2011-02-06 08:02:00 -0800}"
I set firedate for 9:02am chicago absolute time, and timezone to cst - and the log does mention that the fire date is indeed 06:02 my local time. However, nothing happens. Also, next fire date is weird since it should be +1 day, not +2 hrs.
Here's how I set this up:
Class classUILocalNotification = NSClassFromString(#"UILocalNotification");
if (classUILocalNotification != nil) {
id note = [[classUILocalNotification alloc] init];
NSString *body = #"body message";
switch (repeatflag) {
case 1: [note setRepeatInterval:NSDayCalendarUnit]; break;
case 2: [note setRepeatInterval:NSWeekdayCalendarUnit]; break;
case 3: [note setRepeatInterval:NSWeekCalendarUnit]; break;
case 4: [note setRepeatInterval:NSMonthCalendarUnit]; break;
case 5: [note setRepeatInterval:NSYearCalendarUnit]; break;
default: break;
}
[note setFireDate:dt];
[note setAlertBody:body];
[note setTimeZone:timezone];
[note setHasAction:NO];
}
This seems like some unknown behavior. Anyone have a better way to achieve what I am trying to do?
Thanks!
There appears to be a bug with UILocalNotification when using non-local timezone. The first event fired is fired for the correct date and time and timezone. However, subsequent events fire for the given date and time in your local timezone instead of the one set in the setTimeZone method. [iOS 6.1]
Related
I just took a stab at creating some code (pasted below) that would check for a day change. However, now I'm reading that there's a special function for day changes.
NSCalendarDayChangedNotification
Apparently it works in iOS8 and later. But people keep using the phrase "you can listen to it"... as if using that function is like tuning into a radio station. I looked it up and the last WWDC provided a presentation with some relevant code:
Reacting to the Change of Day • You may want to run some code when the
day changes NSCalendarDayChangedNotification • Example
noteCenter = [NSNotificationCenter defaultCenter];
observer = [noteCenter addObserverForName:NSCalendarDayChangedNotification
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
// your code here
}];
My Question
The PDF I found doesn't say much else though. So my question is how does this function work? The PDF makes it seem like it truly is just this simple, paste that code in and I'm done. Is that true? Will it adjust for timezones? Do I have to enable this notification center that it is referencing?
My code (not sure if it would work):
//Find out if it's a new day
let lastDateUsed_NSDefault = NSUserDefaults.standardUserDefaults()
if let endOf_LastDateUsed = lastDateUsed_NSDefault.objectForKey("lastDateUsed") as! NSDate! {
print("Success! NSUserDefault key: 'lastDateUsed' returned \(endOf_LastDateUsed)")
//Check if the day has changed
let calendar = NSCalendar.currentCalendar()
let startOfToday = calendar.startOfDayForDate(now)
if endOf_LastDateUsed.compare(startOfToday) == NSComparisonResult.OrderedAscending {
//endOf_LastDateUsed is greater than startOfToday.
print("Do nothing! Last date used must have been today!")
} else if endOf_LastDateUsed.compare(startOfToday) == NSComparisonResult.OrderedAscending {
//Day has changed. Run alert.
//Save "endOfToday" date value to NSDefault
let endOfToday = startOfToday.dateByAddingTimeInterval(24 * 60 * 60)
NSUserDefaults.standardUserDefaults().setObject(endOfToday, forKey:"lastDateUsed")
print("Time stored in NSDefault: \(endOfToday)")
}
}
else {
print("Failure! NSUserDefault key: 'lasteDateUsed' returned nothing. No record.")
//First time user - Set end of today
let calendar = NSCalendar.currentCalendar()
let startOfToday = calendar.startOfDayForDate(now)
print("startOfToday: \(startOfToday)")
let endOfToday = startOfToday.dateByAddingTimeInterval(24 * 60 * 60)
//Store
NSUserDefaults.standardUserDefaults().setObject(endOfToday, forKey:"lastDateUsed")
print("Time stored in NSDefault: \(endOfToday)")
}
The documentation (which was slightly harder to locate than I'd have hoped, admittedly) is reasonably clear:
Posted whenever the calendar day of the system changes, as determined by the system calendar, locale, and time zone.
So yes, it should handle daylight saving changes appropriately, given that it knows about the time zone. I don't know about enabling the notification centre, but that should be easy enough to test by adjusting the system clock or time zone on a device and seeing what happens.
(What isn't clear from the docs is whether this event is fired if the date is changed via manual intervention, e.g. through changing the system time or time zone in a way that directly changes the date. It would be worth you experimenting with that.)
I'm in a particular situation in which I have to alter the min and max date of DatePicker according to the selected element of a Spinner. Here's the chunk of code I'm using to switch min and max date.
private void switchCalculationMethod(int method) {
calculationMethod = method;
switch (method) {
case METHOD_1:
datePicker.setMinDate(new LocalDate().minusWeeks(42).getMillis());
datePicker.setMaxDate(new LocalDate().plusDays(1).getMillis() - 1);
break;
case METHOD_2:
datePicker.setMinDate(new LocalDate().minusWeeks(2).getMillis()); // This don't work!!
datePicker.setMaxDate(new LocalDate().plusWeeks(40).getMillis()); // This works!!!
break;
}
datePicker.init(today.getYear(), today.getMonthOfYear() - 1,
today.getDayOfMonth(), this);
}
So, the DatePicker would get set up correctly the first time, problem occurs when I attempt to change the min date again (changing max date works). It would remain at the value I had set first. I'm thinking this is a bug. Am I doing something wrong here? Is there a workaround for this?.
PS : I'm using Joda time api.
This happens because method setMinDate() has check
if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
&& mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR){
return;
}
Simple workaround is to set min date with different year at first, for example
mPicker.setMinDate(0);
mPicker.setMinDate(new LocalDate().minusWeeks(2)
.toDateTimeAtStartOfDay().getMillis());
It works for me.
As said above, you can bypass the check by calling those before actually changing the value:
setMinDate(0);
setMaxDate(Long.MAX_VALUE);
If you want to reset the minimum or maximum value to its default, you can use the following values:
setMinDate(-2208902400000L); // Jan 1, 1900
setMaxDate(4102531200000L); // Jan 1, 2100
mPicker.setMinDate(0);
doesn't work for me.
Try to reinitialize the picker.
mPicker = new DatePickerDialog(..)
first update setMinDate to 0 after then setMinDate according to you dateobject
mPicker.setMinDate(0);
mPicker.setMinDate(datepickerObject.getTimeInMillis());
I am making an app that makes a comparison between two dates - one being the current device date and the other being hardcoded date. But one way to fail this logic is, lets say, the hardcoded date is passed and the user changes the device date to a date, which is before the hardcoded date. So in this case the app fails.
How do I avoid this ?
NSDate * currentDate = [NSDate date];
NSDate * hardcodedDate = [[NSDate alloc] initWithString:#"2013-07-21 11:15:30 +0700"];
NSComparisonResult result = [currentDate compare:hardcodedDate];
if (!result == NSOrderedDescending)
{
// do something
}
You would need to get the current date from a web service (using https) in order to verify the date of the users device.
I am using UIDatePicker to select a date. When loading the view date picker minimum date was set with current date, For my specification I need to know is there any modification done in UIDatePicker or not.
if ([[date_picker minimumDate] compare:[date_picker date]] != NSOrderedSame) {
printf("value modified");
}
I have tried with the above condition but its always not matching even though I have not modified the date. Am I doing anything wrong? How do I find that out?
Set control events for datepicker like this
[date_picker addTarget:self
action:#selector(pickerChanged:)
forControlEvents:UIControlEventValueChanged];
and in the pickerChanged method get its value
- (void)pickerChanged:(id)sender{
selectedDate=[sender date];
}
date comparison with
if ([initialDate compare:selectedDate]!=NSOrderedSame)
{
NSLog(#"modified");
// two dates are same and the date formatting of the two dates must be same
}
so whenever you change the date this method will be triggered initialDate is when the view loaded the value is set
I am making an appplication in which i am getting some event response from the server, in the event there are some dates coming related to that event, i need to know how to differentiate between the two dates, In my application there are two segment bars, first one is upcoming events, and second is past events, now i need to show the event related to date in such format, means event is coming in next, need to be show in upcoming events and the events which have gone need to show in past event, All the date are coming from webserver in dd/mm/year format, i have stored all the dates in array and display them in table, however how to differentiate between the coming date and past dates.
NSDate *firstDate = ...
NSDate *secondDate = ...
NSDate *myDate = [NSDate date];
switch ([myDate compare:firstDate]) {
case NSOrderedAscending:
NSLog(#"myDate is older");
// do something
break;
case NSOrderedSame:
NSLog(#"myDate is the same as firstDate");
// do something
break;
case NSOrderedDescending:
NSLog(#"myDate is more recent");
// do something
break;
}
switch ([myDate compare:secondDate]) {
case NSOrderedAscending:
NSLog(#"myDate is older");
// do something
break;
case NSOrderedSame:
NSLog(#"myDate is the same as secondDate");
// do something
break;
case NSOrderedDescending:
NSLog(#"myDate is more recent");
// do something
break;
}
Please read the "Date and Time Programming Guide". It's a great resource for all of your questions. I'd highly recommend you chapters "Creating a Date from Components" and "Calendrical Calculations".