Trying to create UILocalNotification repeating every weekday - ios

I'm trying to create a repeating local notification using Xamarin.IOS. I want to have different alert body message each day, for example "It's monday", "It's tuesday" and so on.
The problem I have is that the only the first notification is working. After I've read the documentation and a few tutorials the correct way to create a repeating notification is to loop through each day and create a total of seven notifications that has the RepeatInterval property set to NSCalendarUnit.Weekday.
My code is a bit messy at the moment...
for (int i = 0; i <= 6; i++) {
NSDateComponents components = gregCalendar.Components (NSCalendarUnit.Day | NSCalendarUnit.Year | NSCalendarUnit.Month, DateTime.Now.AddDays(i).ToNSDate());
components.Day = DateTime.Now.AddDays(i).Day;
components.Month = DateTime.Now.AddDays(i).Month;
components.Year = DateTime.Now.AddDays(i).Year;
NSDate referenceDate = gregCalendar.DateFromComponents (components);
NSDateComponents componentsForFireDate = gregCalendar.Components (NSCalendarUnit.Year | NSCalendarUnit.Hour | NSCalendarUnit.Minute, referenceDate);
componentsForFireDate.Year = components.Year;
componentsForFireDate.Month = components.Month;
componentsForFireDate.Day = components.Day;
componentsForFireDate.Hour = 8;
componentsForFireDate.Minute = 0;
var dayOfWeek = (int)DateTime.Now.AddDays (i).DayOfWeek + 1;
if (dayOfWeek == 8)
dayOfWeek = 1;
componentsForFireDate.Weekday = dayOfWeek;
NSDate fireDateOfNotification = gregCalendar.DateFromComponents (componentsForFireDate);
UILocalNotification localNotification = new UILocalNotification ();
localNotification.FireDate = fireDateOfNotification;
localNotification.TimeZone = NSTimeZone.LocalTimeZone;
localNotification.AlertBody = dayOfWeek;
localNotification.AlertAction = "daily";
localNotification.RepeatCalendar = NSCalendar.CurrentCalendar;
localNotification.RepeatInterval = NSCalendarUnit.Weekday;
localNotification.ApplicationIconBadgeNumber = 1;
UIApplication.SharedApplication.ScheduleLocalNotification (localNotification);
}
My question is, how can I create a local notification that should repeat every day but with different alert body message depending on the weekday?

Add this code into you for loop
switch(i)
{
case 0: //mon
localNotification.alertbody = #"Monday....you message";
break;
case 1 //tue
localNotification.alertbody = #"Tuesday....you message";
break;
case 2://wed
localNotification.alertbody = #"Wednesday....you message";
break;
...
...
}

Related

Weekly Local Notification Showing Array Values - Swift

So let's say I have code like the below local notification code. It runs weekly. How do I change the alertBody string to cycle through an array of messages? My desired end result is that every week it shows array[i], where each time array[i] is incremented +1.
func weeklyNotifications () {
let localNotification = UILocalNotification()
localNotification.fireDate = NSDate(timeIntervalSinceNow: 60*60)
localNotification.alertBody = "Weekly array string"
localNotification.timeZone = NSTimeZone.localTimeZone()
localNotification.repeatInterval = NSCalendarUnit.WeekOfYear
localNotification.soundName = UILocalNotificationDefaultSoundName
localNotification.category = "Message"
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
}
The notification can not cycle the body from an array, the only way is to schedule the notifications yourself (create one for each week) in a loop, and change the body accordingly.
for var i = 0; i < alertBodyMessage.count; i++ {
notification.alertBody = alertBodyMessage[i]
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
you'll have to schedule a notification with alert message from your datasource

Algorithm: Resolution Time

I have an enquiry that needs to be resolved in fixed hour (Critical in 4hr, Important in 10hr and Normal in 24 hr). The enquiry res hours can be increased if there's a non working hour in between or a holiday. Non working can be full day or some hour in a specific day.
For eg: A critical enquiry raised at 08:02am on Monday should get resolved by 01:00pm
//Working hours of week
Mon 09:00am - 01:00pm
Tue Holiday
Wed 09:00am - 05:00pm(non working between 01:00pm - 02:00pm)
Thu 11:00am - 03:00pm(non working between 01:00pm - 02:00pm)
Fri 09:00am - 05:00pm(non working between 01:00pm - 02:00pm)
The inputs are enquiry type and enquiry log time. Output required is the resolution time.
My Approach:
Add all res hours to an enquiry as if all hrs are working. So, if log time is 08:02am for a critical enq add 4hrs i.e. 12:02pm as res time.
Enter while(true) loop where I check if next hr is a work time. If yes skip that hr else add that to res time and continue.
But this approach does not give me correct results when log time is non working.
NSDate *enqExpiration = nil;
int hoursNeededToCoverEnq = 0;
switch (enqType) {
case normalPriority:
hoursNeededToCoverEnq = lowResHours;
enqExpiration = [NSDate dateWithTimeInterval:lowResHours*hour sinceDate:capturedTime];
break;
case importantPriority:
hoursNeededToCoverEnq = mediumResHours;
enqExpiration = [NSDate dateWithTimeInterval:mediumResHours*hour sinceDate:capturedTime];
break;
case criticalPriority:
hoursNeededToCoverEnq = highResHours;
enqExpiration = [NSDate dateWithTimeInterval:highResHours*hour sinceDate:capturedTime];
break;
}
int aggregatedHrs = 0;
while(true){
capturedTime = [NSDate dateWithTimeInterval:1*hour sinceDate:capturedTime];
NSDateFormatter *dayFormat = [[NSDateFormatter alloc] init];
[dayFormat setTimeZone: [NSTimeZone timeZoneWithAbbreviation:#"GMT"]];
[dayFormat setDateFormat:#"EEEE"];
NSString* capturedDay = [dayFormat stringFromDate:capturedTime];
[dayFormat setDateFormat:#"dd/MM/yyyy"];
NSString* todayDate = [dayFormat stringFromDate:capturedTime];
if([weekends containsObject:capturedDay]){
enqExpiration = [NSDate dateWithTimeInterval:1*hour sinceDate:enqExpiration];
continue;
}else if([holidays containsObject:todayDate]){
enqExpiration = [NSDate dateWithTimeInterval:1*hour sinceDate:enqExpiration];
continue;
}else{
NSString *openTime, *closeTime;
for(int i=0; i<weekdaysTime.count; i++){
if([[((NSMutableDictionary*)[weekdaysTime objectAtIndex:i]) valueForKey:#"workingDay"] isEqualToString:capturedDay]){
openTime = [((NSMutableDictionary*)[weekdaysTime objectAtIndex:i]) valueForKey:#"openingTime"];
closeTime = [((NSMutableDictionary*)[weekdaysTime objectAtIndex:i]) valueForKey:#"closingTime"];
break;
}
}
NSDate *openTimeToday = nil, *closeTimeToday = nil;
[dayFormat setDateFormat:#"dd/MM/yyyy hh:mmaa"];
openTimeToday = [dayFormat dateFromString:[[todayDate stringByAppendingString:#" "] stringByAppendingString:openTime]];
closeTimeToday = [dayFormat dateFromString:[[todayDate stringByAppendingString:#" "] stringByAppendingString:closeTime]];
if([capturedTime compare:openTimeToday]==NSOrderedAscending || [capturedTime compare:closeTimeToday]==NSOrderedDescending ){
enqExpiration = [NSDate dateWithTimeInterval:1*hour sinceDate:enqExpiration];
continue;
}
}
aggregatedHrs ++;
if( aggregatedHrs == hoursNeededToCoverEnq )
break;
}
return enqExpiration;

UILocalNotification triggered but not scheduled

Hi people I have a problem with my app, where I want to add some basic LocalNotifications, which repeat themselves every week. I want to do this in a method called "scheduleLocalNotificationForItem:", which is called when the doneBarButtonItem is pressed. This all seems to be working so far, because when I log all the scheduled notifications every scheduled notification shows up. But when I use the app, the scheduled notifications get triggered and show up but there are some additional notifications, which I haven't set myself and I can't determinate where they come from, which appear too.
So here's my code:
- (int)scheduleNotifitactionsForItem:(AlarmItem *)item
{
NSArray *reorderdRepeat = [NSArray arrayWithArray:[self transformArray:item.repeat]];
int missedDays = 0;
int scheduledAlarms = 0;
for (int i = 0; i < item.repeat.count; i++) {
if ([[reorderdRepeat objectAtIndex:i] boolValue] == true) {//Problem determinating true values at end of array
NSInteger integerOfDay = i + 1;//reorderRepeat should contain seven items, icrement i bevore adding it to integerOfDay
NSDate *lastAlarmTime = [self getFireDateForDayOfWeek:integerOfDay withTime:item.time];
NSArray *allAlramTimesForDay = [self getFireDatesForTime:lastAlarmTime andCycle:item.cycles];
for (int i = 0; i < allAlramTimesForDay.count; i++) {
NSDate *alarmTime = [allAlramTimesForDay objectAtIndex:i];
UIApplication *application = [UIApplication sharedApplication];
UILocalNotification *notification = [UILocalNotification new];
NSDictionary *userInfo = #{#"index":[NSString stringWithFormat:#"%d",item.notification]};
notification.repeatInterval = NSCalendarUnitWeekday;
notification.alertBody = item.title;
notification.userInfo = userInfo;
notification.fireDate = alarmTime;
notification.soundName = item.sound;
[application scheduleLocalNotification:notification];
scheduledAlarms += 1;
}
} else {
missedDays += 1;
}
}
return scheduledAlarms;
}
Help is appreciated ;)
Your repeatInterval should be NSCalendarUnitWeekOfYear (or old NSWeekCalendarUnit). NSCalendarUnitWeekday (NSWeekdayCalendarUnit) will repeat everyday.

Setting Reminder with a dueDate with Recurrence Rule iOS

Question: How do I properly set my reminder due date since I have a recurrence rule?
Here is what the reminder object looks like:
EKReminder <0x1700cf490> {title = Dickens's CANINE GOLD WELLNESS doses[1.00]; **dueDate = (null)**; **completionDate = (null)**; priority = 0; calendarItemIdentifier = D1D99FEA-2BFA-4DB1-9D86-7FB26246B50A; alarms = (
"EKAlarm <0x1780a9420> {triggerInterval = -79200.000000}"
)}
The error I am getting is:
Reminder Error=[A repeating reminder must have a due date.]
You can see in the code that I am fooling around with NSDateComponents as a solution since startDateComponents which I just set the month/day/year and local timezone of the reminder which will produce an all day reminder, which in this case is fine. I will probably move the date components and setting of the due date inside the recurrence section when it is done.
Here is my code:
-(void)setReminders:(NSString *)reminderText
andDate:(NSString *)reminderdate
andPetName:(NSString*)petName
andDose:(NSNumber *)dose {
EKEventStore *store = [[EKEventStore alloc] init];
NSDate * reminderNewDate = [self getDateFromString:reminderdate];
petName = [ConfigOps readProperty:kConfigOpsPetKey];
NSString *reminderTitle = [NSString stringWithFormat:#"%#'s %#", petName, reminderText];
NSUInteger doseCount = 0;
if ([dose integerValue] != 0 || dose != nil) {
doseCount = [dose integerValue];
}
else{
doseCount = 0;//NOTE: looks like purchases will have doses not reminders so set to 0 for now.
}
[store requestAccessToEntityType:EKEntityTypeReminder completion:^(BOOL granted, NSError *error) {
// access code here
EKReminder *new_reminder = [EKReminder reminderWithEventStore:store];
new_reminder.title = reminderTitle;
new_reminder.calendar = store.defaultCalendarForNewEvents;
//get the date components
NSDateComponents *comp = [[NSDateComponents alloc]init];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *weekdayComponents =
[gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit |
NSWeekdayCalendarUnit) fromDate:reminderNewDate];
NSInteger day = [weekdayComponents day];
NSInteger month = [weekdayComponents month];
//NSInteger weekday = [weekdayComponents weekday];//future reference
NSInteger year = [weekdayComponents yearForWeekOfYear];
//Month is dose+month = end of reccurence
month = month + doseCount;
[comp setYear:year];
[comp setMonth:month];
[comp setDay:day];
NSDate *date = [gregorian dateFromComponents:comp];
NSTimeZone *myNSTimeZone = gregorian.timeZone;
NSDateComponents *start = new_reminder.startDateComponents;
start.timeZone = myNSTimeZone;
start.month = [weekdayComponents month];
start.day = [weekdayComponents day];
start.year = [weekdayComponents yearForWeekOfYear];
new_reminder.startDateComponents = start;
new_reminder.dueDateComponents = start;
new_reminder.completed = NO;
//Create alarm 22 hours before
double alarmAmountInSeconds = 60.0*60.0*22.0;
EKAlarm *alarm = [EKAlarm alarmWithRelativeOffset:(-1.0*alarmAmountInSeconds)];
[new_reminder addAlarm:alarm];
//new_reminder.alarms = [NSArray arrayWithObject:alarm];
//create nice text for note.
//Hey there! petName needs remindertext from your friendly clinic, clinicName!
new_reminder.notes = reminderText;
if (doseCount != 0) {
EKRecurrenceRule *recurranceRule = [[EKRecurrenceRule alloc] initRecurrenceWithFrequency:EKRecurrenceFrequencyMonthly
interval:1
end:[EKRecurrenceEnd recurrenceEndWithOccurrenceCount:doseCount]
];
new_reminder.calendar = [store defaultCalendarForNewReminders];
[new_reminder addRecurrenceRule:recurranceRule];
}
NSError *er;
//EKEventEditViewController
BOOL success = [store saveReminder:new_reminder commit:YES error:&er];
if (success) {
// Handle here
NSString *alertMessage = [NSString stringWithFormat:#"Reminder Created for\n%#", reminderTitle];
NSString *alertTitle = #"Please check your Reminders";
UIAlertView *alertR = [[UIAlertView alloc]initWithTitle: alertTitle
message: alertMessage
delegate: self
cancelButtonTitle:nil
otherButtonTitles:#"OK",nil];
[alertR show];
}
else{
//log error
NSLog(#" Reminder Error=[%#]", [er localizedDescription]);
//log to error table in database &inform Flurry?
}
}];
}
The method works if there is no recurrence set since it doesn't require a start date/due date.
After some fixing of the date (I found was returning nil), I found that I have to set and end recurrence rule when adding a dose amount.
Here is the code which gets rid of the error (which is pretty funny of Apple to have - kudos Apple!).
if (doseCount != 0) {
EKRecurrenceRule *recurranceRule = [[EKRecurrenceRule alloc] initRecurrenceWithFrequency:EKRecurrenceFrequencyMonthly
interval:1
end:[EKRecurrenceEnd recurrenceEndWithOccurrenceCount:doseCount]
];
new_reminder.calendar = [store defaultCalendarForNewReminders];
//FIX for : recuurence end - Reminder Error = [A repeating reminder must have a due date.]
EKRecurrenceEnd *endRec = [EKRecurrenceEnd recurrenceEndWithEndDate:date];
EKRecurrenceRule *recur = [[EKRecurrenceRule alloc]initRecurrenceWithFrequency:EKRecurrenceFrequencyDaily interval: 1 end:endRec];
unsigned unitFlags= NSYearCalendarUnit|NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit |NSMinuteCalendarUnit|NSSecondCalendarUnit|NSTimeZoneCalendarUnit;
NSDateComponents *dailyComponents=[gregorian components:unitFlags fromDate:date];
[new_reminder setDueDateComponents:dailyComponents];
[new_reminder addRecurrenceRule:recur];
//add it.
[new_reminder addRecurrenceRule:recurranceRule];
}
Hope this helps someone get through this.
For those looking for Swift version:
func editReminder(r: EKReminder) -> Bool {
if(r.recurrenceRules.count > 0 && r.dueDateComponents == nil) {
let startDate = NSDate()
let dueDate: NSDate = NSDate(timeIntervalSinceNow: 31536000) // 1 year from now
let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
let unitFlags = NSCalendarUnit(UInt.max)
r.dueDateComponents = gregorian?.components(unitFlags, fromDate: dueDate)
}
var error: NSError?
return eventStore.saveReminder(r, commit: true, error: &error)
}

Local Notification Ever Changing Text

I am working on getting local notifications to fire at a time every day (set by the user). I have done this in the past, but just where it was one static message that would get shown every day. I would like for it to take the text for the local notification from a plist file I have made with each row being a quote. Is there a way to fire local notifications, but have it change the text every day?
I have right now:
- (IBAction)scheduleNotification {
Class cls = NSClassFromString(#"UILocalNotification");
if (cls != nil) {
UILocalNotification *notif = [[cls alloc] init];
notif.fireDate = [datePicker date];
notif.timeZone = [NSTimeZone defaultTimeZone];
notif.alertBody = #"Today's 5 Minutes With God Study Is Now Available";
notif.alertAction = #"Ok";
notif.soundName = UILocalNotificationDefaultSoundName;
notif.applicationIconBadgeNumber = 1;
NSInteger index = [scheduleControl selectedSegmentIndex];
switch (index) {
case 0:
notif.repeatInterval = NSDayCalendarUnit;
break;
case 1:
notif.repeatInterval = 0;
break;
}
NSDictionary *userDict = [NSDictionary dictionaryWithObject:#"Today's Quote!"
forKey:kRemindMeNotificationDataKey];
notif.userInfo = userDict;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
[self.notifications addObject:notif];
[notif release];
}
}
So, how would I get the alertBody to show a different message each day?
You have to create a new notification every time, for every new message.

Resources