UILocalNotifications repeatInterval using NSWeekdayCalendarUnit - uilocalnotification

OK, so I have seen several posts that say you cannot set a UILocalNotification to repeat any more or less than a few given options (every minute/hour/day/week/month etc.).
However, none of those posts addressed what setting the repeatInterval property of UILocalNotification to NSWeekdayCalendarUnit would do.
I'm very new to all this NSDate and NSCalendar stuff, so I am sure I am missing something, but I have read over the documentation and, it sounds like you CAN use NSWeekdayCalendarUnit to make a NSLocalNotification repeat say, every Monday, Tuesday and Thursday if NSWeekdayCalendarUnit is set to 2,3,5.
NSWeekdayCalendarUnit
Specifies the weekday unit.
The corresponding value is an int. Equal to kCFCalendarUnitWeekday. The weekday units are the numbers 1 through N (where for the Gregorian calendar N=7 and 1 is Sunday).
Is that not correct?
Thanks in advance.

Yes you can. I do it like this. The user can choose a scheme with a picker. And then the choice goes to the following method:
- (void)setOneLocalAlarmNotification: (NSDate *)firstFireDate withRepeat: (NSInteger)repeat {
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = firstFireDate;
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.repeatCalendar = [NSCalendar currentCalendar];
switch(repeat) {
case 0:
break ;
case 1:
localNotif.repeatInterval = kCFCalendarUnitDay;
break;
case 2:
localNotif.repeatInterval = kCFCalendarUnitWeekday;
break;
default:
break;
}
// Notification details
localNotif.alertBody = #"Message?";
// Set the action button
localNotif.alertAction = #"Yes";
localNotif.soundName = #"glas.caf"; //UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber = 1;
// Specify custom data for the notification
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:#"Alarm" forKey:#"type"];
localNotif.userInfo = infoDict;
// Schedule the notification
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
[localNotif release]
}

Related

Xcode preprocessor macro for dates

I want to "hardcode" an expiration date into my beta code. Right now I manually calculate a unix date and compare that to the current date time:
if([[NSDate date] timeIntervalSince1970]>1422748800) mustHalt = TRUE;
I'd like a way of replacing the 1422748800 with a macro that generates the equivalent number for a date 90 days in the future at compile time.
Any suggestions?
The predefined macro __DATE__ is what you need. Here is a SO question related to this. But maybe you want to use a code like this:
const int daysToExpire = 14;
NSString *compileDate = [NSString stringWithUTF8String:__DATE__];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"MMM d yyyy"];
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[df setLocale:usLocale];
NSDate *expireDate = [df dateFromString:compileDate];
bool isExpired = ([[NSDate date] compare:expireDate] == NSOrderedDescending); // decide for it

How to calculate and display 4 other days from the day i add in date picker and set local notification to it?

In my App, When i select a day in the datepicker it should automatically calculate and display 4 other days and also it should notify on the corresponding days. For Eg. if i enter 19-08-2014, it should calculate and display the 3rd day, the 7th day, the 14th day and the 21st day from 19-08-2014(the day i entered in datepicker).
How would i achieve this. Any help would be greatly appreciated.
I have added my current code for your reference. This doesnt serve my purpose.
Kindly Help.
(IBAction)save:(UIButton *)sender {
NSDate *pickerDate = [self.picker date];
UILocalNotification *localNotif = [[UILocalNotification alloc]init];
//localNotif.alertBody = _enterText.text;
localNotif.alertBody = #"Please Take Your Rabipur Dosage";
localNotif.fireDate = pickerDate;
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.soundName = (UILocalNotificationDefaultSoundName);
localNotif.applicationIconBadgeNumber = 1;
//localNotif.repeatInterval = NSDayCalendarUnit;
[[UIApplication sharedApplication]scheduleLocalNotification:localNotif];
[self dismissViewControllerAnimated:YES completion:nil];
}
Create an NSDateComponents object with the date difference you want to add, and add it to pickerDate via NSCalendar -dateByAddingComponents:toDate:options. Then create your notification based on the resulting date.
In this case, something like this:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setDay:3];
NSDate *reminderDate = [gregorian dateByAddingComponents:offsetComponents toDate:pickerDate options:0];
Repeat for 7th, 14th, and 21st day.

Calculate seconds between current time and next event

This should be simple, but it's proving challenging for me. I'd like to know the best approach to calculating the difference in seconds between [NSDate date] and a future event x seconds from that time. There are several different types of event, and each event may occur several times a day, and at different times, depending what day of the week it happens to be.
What I am trying to do is have the user select an event type from a picker and then set an alarm in Notification Center for the next occurrence of that event based on their selection. I have everything working fine, except for the seconds calculation.
So, for example, let's say it's 9am on a Monday. I'd like to determine how many seconds it would be between now and a user selected event that regularly occurs every Tuesday, Thursday, and Saturday at 10am, 4pm, and 11pm on each day, or on Sunday at 1pm. How would you approach this most efficiently?
When you're talking about a time or date like "next Thursday at 1 PM", that's information that only makes sense in the context of a calendar. NSDate is not going to provide you with much help. It would perhaps be more appropriately named NSPointInTime. It's just a number of seconds that have passed from some earlier, arbitrary reference point in time. It has no notion of weekdays, ante/post meridiem, or even hour of the day.
The two objects that do know about those sorts of thing are NSDateComponents and NSCalendar. Working together, they can create an NSDate from a specification like "next Thursday at 1PM".
You can decompose any date into components using -[NSCalendar components:fromDate:], and you can then use other NSDateComponents objects to perform arithmetic on the individual pieces of information. Find the weekday of today, for example, and its difference from Thursday. Then use -[NSCalendar dateByAddingComponents:toDate:options:] to create a new date based on that offset.
#interface NSCalendar (NextWeekday)
- (NSInteger)maxWeekday;
- (NSDate *)dateFromComponents:(NSDateComponents *)comps
forNextWeekday:(NSInteger)weekday
atHour:(NSInteger)hour;
#end
#implementation NSCalendar (NextWeekday)
- (NSInteger)maxWeekday
{
return [self maximumRangeOfUnit:NSWeekdayCalendarUnit].length;
}
- (NSDate *)dateFromComponents:(NSDateComponents *)comps
forNextWeekday:(NSInteger)weekday
atHour:(NSInteger)hour
{
NSInteger diff = weekday - [comps weekday];
if( diff < 0 ){
diff += [self maxWeekday];
}
NSDateComponents * weekdayOffset = [NSDateComponents new];
[weekdayOffset setWeekday:diff];
[comps setHour:hour];
return [self dateByAddingComponents:weekdayOffset
toDate:[self dateFromComponents:comps]
options:0];
}
#end
#define GREGORIAN_THURSDAY 5
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSCalendar * cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents * wednesday = [NSDateComponents new];
[wednesday setDay:3];
[wednesday setWeekday:4];
[wednesday setMonth:6];
[wednesday setYear:2013];
NSDateComponents * friday = [NSDateComponents new];
[friday setDay:5];
[friday setWeekday:6];
[friday setMonth:6];
[friday setYear:2013];
NSDateComponents * now = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSWeekdayCalendarUnit
fromDate:[NSDate date]];
NSDateComponents * lastSatOfDecember = [NSDateComponents new];
[lastSatOfDecember setDay:29];
[lastSatOfDecember setWeekday:7];
[lastSatOfDecember setMonth:12];
[lastSatOfDecember setYear:2012];
NSLog(#"From Wednesday: %#", [cal dateFromComponents:wednesday
forNextWeekday:GREGORIAN_THURSDAY
atHour:13]);
NSLog(#"From Friday: %#", [cal dateFromComponents:friday
forNextWeekday:GREGORIAN_THURSDAY
atHour:13]);
NSLog(#"From now: %#", [cal dateFromComponents:now
forNextWeekday:GREGORIAN_THURSDAY
atHour:13]);
NSLog(#"Crossing over the year: %#", [cal dateFromComponents:lastSatOfDecember
forNextWeekday:GREGORIAN_THURSDAY
atHour:13]);
}
return 0;
}

Core-Plot: Wrong date on x-Axis

Following different tutorials, I've successfully created a scatter plot using Core-Plot. Now, setting dates on X-Axis I'm obtaining totally wrong dates.
The source of my graph is an array containing a dictionary. In every record of the dictionary the first key of the dictionary is a unix timestamp and the second key, the value to draw. It looks like this:
(
{
0 = 1334152500;
1 = 0;
},
{
0 = 1334152800;
1 = 0;
},
{
0 = 1334153100;
1 = 0;
},
AFAIK Core-Plot Needs a start date and a step. In this case start date is 1334152500 (Wed, 11 Apr 2012 13:55:00 GMT) and step is 300 seconds. Every 300 seconds a new value is present.
Now the code I use to draw the X-axis:
// this string contains the first UNIX Timestamp registered
NSString *tstamp_start = [NSString stringWithFormat:#"%#", [[[self.graphData objectForKey:#"1"] objectAtIndex:0] objectForKey:#"0"]];
NSDate *refDate = [NSDate dateWithTimeIntervalSince1970:[tstamp_start doubleValue]];
// definition of the graph skipped...
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)self.graph.axisSet;
// tInterval is previous set to 300 - float.
// here I should set the Interval between every value on graph...
axisSet.xAxis.majorIntervalLength = CPTDecimalFromFloat(tInterval);
axisSet.xAxis.axisLineStyle = axisLineStyle;
axisSet.xAxis.majorTickLineStyle = axisLineStyle;
axisSet.xAxis.minorTickLineStyle = axisLineStyle;
axisSet.xAxis.labelTextStyle = textStyle;
axisSet.xAxis.labelOffset = 3.0f;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd/MM/yyyy hh:mma"];
CPTTimeFormatter *timeFormatter = [[CPTTimeFormatter alloc] initWithDateFormatter:dateFormatter];
timeFormatter.referenceDate = refDate;
axisSet.xAxis.labelFormatter = timeFormatter;
axisSet.xAxis.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
axisSet.xAxis.orthogonalCoordinateDecimal = CPTDecimalFromFloat(yAxisMin);
(...)
The line is correctly shown, but on X Axis I'm reading values/labels like: '22/07/2054 06:35AM'. Year 2054? Without considering the timezone (local +2, unix +0) and CPTAxisLabelingPolicyAutomatic, at least I should read a date between 13:55 and now on current day. What I'm missing?
Thank's a lot!
Simon
The referenceDate is the offset applied to each data point when formatting. Therefore, the value of the first data point is being doubled. You either need to adjust the reference date or change the data values to start from 0.
NSDate *refDate = [NSDate dateWithTimeIntervalSince1970:0.0];

Time comparison in Cocoa

I am storing the date and time in strings using NSUserDefaults when an action is performed. next time the app is run, I want to check the time since the last date and time, and display a message if this is greater than a specified time period.
Is this possible?
In viewDidLoad I retrieve the NSUserDefaults with the saved date and time, and I get the current date, but how do i compare them, and 'do something' if the time difference is bigger than specified?
Use NSDate's timeIntervalSinceDate: method.
By the way, you can store NSDates directly in NSUserDefaults. You don't need to convert them to/from strings.
You could do something like that:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDate * lastUpdate = [defaults valueForKey:#"mysettingdate"];
if(!lastUpdate){
lastUpdate = [NSDate dateWithTimeIntervalSince1970:0];
}
NSDate *localDate = [NSDate date];
NSTimeInterval timeZoneOffset = [[NSTimeZone defaultTimeZone] secondsFromGMT];
NSTimeInterval gmtTimeInterval = [localDate timeIntervalSinceReferenceDate] + timeZoneOffset;
NSDate *gmtDate = [NSDate dateWithTimeIntervalSinceReferenceDate:gmtTimeInterval];
NSDateComponents *diff = [[NSCalendar currentCalendar] components:NSMinuteCalendarUnit fromDate:lastUpdate toDate:gmtDate options:0];
NSLog(#"diff in minutes:%d", [diff minute]); //or hour, days, seconds
if ([diff minute]>0) {
//do your stuff :)
}

Resources