UILocalNotification repeatInterval on 20 days - ios

I'd like to create local notification with custom interval repeat (every 20 days for example).
I know we have NSDayCalendarUnit, kCFCalendarUnitMonth ... but I hope to set repeat interval at 20 days.
I don't want to create a notification for every day.
My real need is to repeat a notification for consecutive 21 days, then don't launch it for 7 days later, then a new 21 days with notification and 7 days without ... etc.
I should schedule all these days even if application is inactive.
To do this I decide to create a 21 notifications since a fire date with repeatInterval = 28days (here is the problem)

Try this, you can change the intervall by selecting setDay, setMonth, .... :
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:3];
NSDate *date3Days = [calendar dateByAddingComponents:components
toDate:[NSDate date]
options:0];
UIApplication* app = [UIApplication sharedApplication];
NSArray* oldNotifications = [app scheduledLocalNotifications];
if ( oldNotifications ) {
[app cancelAllLocalNotifications];
app.applicationIconBadgeNumber = 0;
}
UILocalNotification* notifyAlarm = [[UILocalNotification alloc] init];
if (notifyAlarm) {
notifyAlarm.fireDate = date3Days;
notifyAlarm.timeZone = [NSTimeZone defaultTimeZone];
notifyAlarm.alertBody = NSLocalizedString( #"Push message", #"");
notifyAlarm.soundName = #"sound.wav";
[app scheduleLocalNotification:notifyAlarm];
}
If you want to set a specific time after which the UILocalNotifications should appear you can create a method of the above solution and loop over an array which indicates the days you like to show a notification:
NSArray *arrayNumbers = #[#5, #7, #14, #21, #30, #60, #90, #120];
NSDictionary *dictNotifications =
[[NSUserDefaults standardUserDefaults] objectForKey:kUserDefAppStarts];
for ( NSNumber *bla in arrayNumbers ){
NSString *strKey = [NSString stringWithFormat:#"%#%#", kUserDefAppStarts, bla];
NSDictionary *dict = dictNotifications[strKey];
NSString *strMessageQuestion = dict[kKeyMessage];
[self createNotificationWithNumberOfDays:[bla integerValue]
andMessage:strMessageQuestion
userInfo:dict];
}
And here is the method you have to call
+ (void)createNotificationWithNumberOfDays:(int)days
andMessage:(NSString *)message
userInfo:(NSDictionary *)dict{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:days];
NSDate *dateAlert = [gregorian dateByAddingComponents:components toDate:[NSDate date] options:0];
UIApplication *app = [UIApplication sharedApplication];
UILocalNotification *notifyAlarm = [[UILocalNotification alloc] init];
if( notifyAlarm ){
[notifyAlarm setFireDate:dateAlert];
[notifyAlarm setTimeZone:[NSTimeZone defaultTimeZone]];
[notifyAlarm setSoundName:#"soundname"];
[notifyAlarm setAlertBody:message];
[notifyAlarm setUserInfo:dict];
[app scheduleLocalNotification:notifyAlarm];
}
}

If you wanted to schedule a UILocalNotification for 20 days in the future from the current time you would do this:
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSDateComponents *dateComp = [[NSDateComponents alloc] init];
int desiredAmountOfMonths = 4;
for (int month = 0; month < desiredAmountOfMonths; month++)
{
dateComp.month = month;
dateComp.day = 20;
NSDate *fireDate = [currentCalendar dateByAddingComponents:dateComp toDate:[NSDate date] options:NSCalendarMatchNextTimePreservingSmallerUnits];
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = fireDate;
notification.timeZone = [NSTimeZone defaultTimeZone];
}
You will need to modify the UILocalNotification for what message, sound, etc and then fire the notification once done customizing.

Related

How to notify a notification message at every month end day

How to notify every month notification.
-(void)applicationDidEnterBackground:(UIApplication *)application {
NSDateFormatter *format = [[NSDateFormatter alloc] init];
format.dateFormat = #"dd-MM-yyyy";
NSComparisonResult result = [[format stringFromDate:[NSDate new]] compare:[format stringFromDate:[self lastDayOfMonthOfDate:[NSDate date]]]];
if (result == NSOrderedSame){
if (![USERDEFAULTS boolForKey:#"IS_MONTH"]) {
[self getNotifiedForEveryMonth:nil];
}}
else{
[USERDEFAULTS setBool:NO forKey:#"IS_MONTH"];
}
}
// getNotifiedForEveryMonth
-(void)getNotifiedForEveryMonth:(id)userinfo{
// Schedule the notification
[USERDEFAULTS setBool:YES forKey:#"IS_MONTH"];
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = [NSDate date];
localNotification.alertBody = #"Every Month Notificiation";
localNotification.alertAction = #"Show me the item";
localNotification.timeZone = [NSTimeZone defaultTimeZone];
}
-(NSDate*)lastDayOfMonthOfDate:(NSDate *)date
{
// NSGregorianCalendar
NSInteger dayCount = [self numberOfDaysInMonthCountForDate:date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
[calendar setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
NSDateComponents *comp = [calendar components:
NSCalendarUnitYear |
NSCalendarUnitMonth |
NSCalendarUnitDay fromDate:date];
[comp setDay:dayCount];
return [calendar dateFromComponents:comp];
}
-(NSInteger)numberOfDaysInMonthCountForDate:(NSDate *)date
{
NSCalendar *calendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
[calendar setTimeZone:[NSTimeZone timeZoneWithName:TIME_ABSOLUTE]];
NSRange dayRange = [calendar rangeOfUnit:NSCalendarUnitDay
inUnit:NSCalendarUnitMonth
forDate:date];
return dayRange.length;
}
The above code with i try to notify the notification.
Its getting notification every month end day,
If user close the notification and then next month comes the notifcation is not notifying.
After installation the application, how to notify the user very month end day a notification message.
Your inputs are appreciated.
1) If you want fire notifications every month, even if user didn't open an app more then month, you should set several notifications (up to 60). For example, set notifications for next 12 month.
2) You should set notifications by this code (on loop, 12 times):
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
3) Before you set new notifications, remove old with this code:
[[UIApplication sharedApplication] cancelAllLocalNotifications];

ios. Disable everyday notification if it is already irrelevant

I want to remind user to take photo everyday. I use code for every day local push notificatons
UILocalNotification *everyDayNotification = [[UILocalNotification alloc] init];
everyDayNotification.repeatInterval = NSDayCalendarUnit;
NSDate *currentDate = [[NSDate alloc] init];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:currentDate];
int hour = [hours_string intValue];
int minutes = [minutes_string intValue];
[components setHour:hour];
[components setMinute:minutes];
NSDate *today10am = [calendar dateFromComponents:components];
everyDayNotification.fireDate = today10am;
everyDayNotification.timeZone = [NSTimeZone defaultTimeZone];
everyDayNotification.alertBody = #"It us time";
everyDayNotification.alertAction = #"Action";
everyDayNotification.soundName = UILocalNotificationDefaultSoundName;
everyDayNotification.applicationIconBadgeNumber = 1;
NSDictionary *userDict = [NSDictionary dictionaryWithObject:#"EveryDay"
forKey:#"RemindNotificaion"];
everyDayNotification.userInfo = userDict;
[[UIApplication sharedApplication] scheduleLocalNotification:everyDayNotification];
But if the user has made the photo before it is time to notice that. I want to skip the notification for today. Is that possible?
I would suggest making an individual UILocalNotification for each day and storing them, perhaps in an array in NSUserDefaults. Then you can cancel a notification with the following:
[[UIApplication sharedApplication] cancelLocalNotification:notficiationInstance];

How to allocate custom time in UILocalnotification?

- (void)scheduleNotification :(int) rowNo
{
[[UIApplication sharedApplication] cancelAllLocalNotifications];
Class cls = NSClassFromString(#"UILocalNotification");
if (cls != nil) {
UILocalNotification *notif = [[cls alloc] init];
notif.timeZone = [NSTimeZone defaultTimeZone];
NSString *descriptionBody=[[remedyArray objectAtIndex:rowNo]objectForKey:#"RemedyTxtDic"];
NSLog(#"%#",descriptionBody);
notif.alertBody = [NSString stringWithString:descriptionBody];
notif.alertAction = #"Show me";
notif.soundName = UILocalNotificationDefaultSoundName;
notif.applicationIconBadgeNumber = 1;
NSDictionary *userDict = [NSDictionary dictionaryWithObject:notif.alertBody
forKey:#"kRemindMeNotificationDataKey"];
notif.userInfo = userDict;
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
}
}
I have a column name frequency which is fetched from Sqldb where it contains the number of times notification should appear for a particular cell.
if frequency = 3 ..the notification should fire say 8 AM , 2PM then 8PM
if frequency = 4 ..the notification should fire say 8 AM , 12PM , 4PM then 8PM.
Is there a way to do it? If anyone can help me that would be great
Unfortunately, You can specify value for repeatInterval only of type NSCalendarUnit (day, week, month). So, I think, You need to create several Notifications with different fireDate, and specify for them repeatInterval = NSDayCalendarUnit
For example,
NSDate *currentTime = [NSDate date];
notification1.fireDate = [NSDate dateWithTimeInterval:SOME_INTERVAL sinceDate:currentTime];
notification1.repeatInterval = NSDayCalendarUnit;
notification2.fireDate = [NSDate dateWithTimeInterval:SOME_INTERVAL * 2 sinceDate:currentTime];
notification2.repeatInterval = NSDayCalendarUnit;
After user viewed some of notifications - You can cancel them.
Update.
You can also create NSDate from different components like this:
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setWeekday:2]; // Monday
[components setWeekdayOrdinal:1]; // The first Monday in the month
[components setMonth:5]; // May
[components setYear:2013];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:components];
Also You can set hour, minutes, seconds, timezone and other parameters.

IOS CancelNotificaion on particular date when the app is in Background

I am working on a application that reminds about the expiry date. I have implemented the same using UILocalNotification with repeat Interval (NSMonthCalendarUnit, NSDayCalendarUnit,NSDayCalendarUnit). For example I have the fire date on 01-01-2012 and the repeat interval is NSDayCalendarUnit and the end date is 12-12-2012, is it possbile to cancelLocalNotification: on expiry.
here is the code:-
- (void) scheduleNotificationOn:(NSDate*) fireDate
text:(NSString*) alertText
action:(NSString*) alertAction
sound:(NSString*) soundfileName
launchImage:(NSString*) launchImage
andInfo:(NSDictionary*) userInfo
{
userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
txtExpiryDate.text, #"ExpiryDate",
txtRegNo.text , #"RegNo",
nil];
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = fireDate;
localNotification.timeZone = [NSTimeZone systemTimeZone];
localNotification.userInfo = userInfo;
localNotification.alertBody = alertText;
localNotification.alertAction = alertAction;
NSLog(#"Repeat Type:%#",txtRepeat.text);
if([txtRepeat.text isEqualToString:#"Every Week"])
{
NSLog(#"Every Week");
localNotification.repeatInterval = 256;
}
else if([txtRepeat.text isEqualToString:#"Every Month"])
{
NSLog(#"Every Month");
localNotification.repeatInterval = NSMonthCalendarUnit;
}
else if([txtRepeat.text isEqualToString:#"Every Day"])
{
NSLog(#"Every Day");
localNotification.repeatInterval = NSDayCalendarUnit;
}
if(soundfileName == nil)
{
localNotification.soundName = UILocalNotificationDefaultSoundName;
}
else
{
localNotification.soundName = soundfileName;
}
NSLog(#"appDelegate.BadgeNumber:%d",appDelegate.BadgeNumber);
localNotification.alertLaunchImage = launchImage;
appDelegate.BadgeNumber = appDelegate.BadgeNumber + 1;
localNotification.applicationIconBadgeNumber = appDelegate.BadgeNumber;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
[localNotification release];
}
I have worked by comparing current date to expiry date. But this work only if the app is in foreground and i cannot cancelnotification not background for a particular date. Please find the below code for the same:-
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
BadgeNumber = 0;
application.applicationIconBadgeNumber = BadgeNumber;
NSArray *localNotifications = [[UIApplication sharedApplication] scheduledLocalNotifications];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
NSDateFormatter *formatter =[[[NSDateFormatter alloc]init] autorelease];
[formatter setDateFormat:#"dd/MM/yyyy"];
NSLog(#"localNotifications Count %d",localNotifications.count);
for (UILocalNotification *notify in localNotifications)
{
//notify.applicationIconBadgeNumber = 0;
NSString *ExpiryDateString = [notify.userInfo objectForKey:#"ExpiryDate"];
NSDate *ExpiryDate = [formatter dateFromString:ExpiryDateString];
NSDate * NextFireDate = nil;
NSLog(#"Expiry Date:%#",ExpiryDateString);
if(notify.repeatInterval == NSDayCalendarUnit)
{
NSLog(#"Repeat Every Day");
NextFireDate = [[NSDate date] dateByAddingDays:1];
NSLog(#"Next FireDate: %#",[formatter stringFromDate:NextFireDate]);
}
if(notify.repeatInterval == NSWeekCalendarUnit)
{
NSLog(#"Repeat Every Day");
NextFireDate = [[NSDate date] addTimeInterval:D_WEEK];
NSLog(#"Next FireDate: %#",[formatter stringFromDate:NextFireDate]);
}
if(notify.repeatInterval == NSMonthCalendarUnit)
{
NSLog(#"Repeat Every Day");
//NextFireDate = [[NSDate date] addTimeInterval:D_Month];
NextFireDate = [self CalculateExipiryDateForMonth];
NSLog(#"Next FireDate: %#",[formatter stringFromDate:NextFireDate]);
}
NSComparisonResult result = [NextFireDate compare:ExpiryDate];
NSLog(#"NSComparisonResult:%d",result);
if(result == NSOrderedDescending)
{
NSLog(#"Cancell......... Notification");
NSLog(#"notify :::%#",notify);
}
else
{
NSLog(#"Re-Schedule Notification");
BadgeNumber = BadgeNumber + 1;
notify.applicationIconBadgeNumber = BadgeNumber;
NSLog(#"BadgeNumber:%d",BadgeNumber);
[[UIApplication sharedApplication] scheduleLocalNotification:notify];
}
}
}
-(NSDate*) CalculateExipiryDateForMonth
{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
components.month = 1;
NSDate *nextMonth = [gregorian dateByAddingComponents:components toDate:[NSDate date] options:0];
[components release];
NSDateComponents *nextMonthComponents = [gregorian components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:nextMonth];
NSDate *expiryDay = [gregorian dateFromComponents:nextMonthComponents];
NSDateComponents *dayComponent = [[NSDateComponents alloc] init];
dayComponent.day = -1;
NSDate *NewExpiry = [gregorian dateByAddingComponents:dayComponent toDate:expiryDay options:0];
[gregorian release];
[dayComponent release];
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:#"dd/MM/yyyy"];
NSLog(#"Next Exipiry Date -----:%#",[formatter stringFromDate:NewExpiry]);
return NewExpiry;
}
In short, no, you cannot cancel a UILocalNotification while your app is running in the background.
**Apple RESPONSE:-**
I'm responding to your question about UILocalNotification.
At this time UILocalNotification does not have a way to specify an expiry
date or number of repetitions before the notification is automatically
canceled.
The closest you can get today is to schedule up to 64 individual
notifications instead of using the repeat interval.
But you're correct; if the user doesn't ever bring your app to the
foreground, it won't have the opportunity to cancel or reschedule local
notifications.
I highly recommend that you file an enhancement request at <
https://developer.apple.com/bugreporter> asking for this functionality in a
future release of iOS.
You also asked about what happens to local notifications when the user
removes your app from the device. iOS stores the local notifications so
that they are still scheduled if the user deletes and then reinstalls the
app.
When your app runs, it can check the scheduledLocalNotifications property
of UIApplication and remove any notifications that are no longer relevant.
Best regards,
--gc
Garth Cummings
Apple Developer Technical Support

iOS – UILocalNotification fired twice for same notification

If I schedule two UILocalNotifications and set them both to fire at the exact same fireDate. Then on the device (this is not the simulator bug) on the fireDate the application:didReceiveLocalNotification: will fire 4 times (2 times for each notification). Is this a known bug? Because I have not been able to find any information about it.
Please report the bug to http://bugreport.apple.com.
Having said that, it has been noticed before that while there is the bug in the simulator there also appears to be a bug on the device.
See the comments and answers on this SO question: local notification "didReceiveLocalNotification" calls twice
try this it's work in my application :
-(IBAction)setRemind:(id)sender{
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
NSDateFormatter *dateFormatter2 = [[NSDateFormatter alloc] init];
[dateFormatter2 setDateFormat:#"YYYY-MM-dd HH:mm:ss"];
//Gets our picker
NSDate *selectedTime = [datePicker date];
strDate2 = [dateFormatter2 stringFromDate:selectedTime];
NSDate *Date=[dateFormatter2 dateFromString:strDate2];
NSDateComponents *dateComponents = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit ) fromDate:Date];
// Set up the fire time
NSDateComponents *dateComp = [[NSDateComponents alloc] init];
[dateComp setDay:[dateComponents day]];
[dateComp setMonth:[dateComponents month]];
[dateComp setYear:[dateComponents year]];
[dateComp setHour:9];
[dateComp setMinute:00];
[dateComp setSecond:00];
[dateComp release];
NSDate *date = [calendar dateFromComponents:dateComp];
[self scheduleAlarmForDate:date message:txtDescri.text];
}
-(IBAction)scheduleAlarmForDate:(NSDate*)date message:(NSString*)msg
{
//====== TO SEE OLD NOTIFI=======
UIApplication *Ap = [UIApplication sharedApplication];
NSArray *arr = [Ap scheduledLocalNotifications];
NSLog(#"Old Notifications :>> %#",arr);
UIApplication* app = [UIApplication sharedApplication];
UILocalNotification *alarm = [[UILocalNotification alloc] init];
// Create a new notification
alarm.fireDate = date;
NSLog(#"fireDate IS >> %#", alarm.fireDate);
alarm.timeZone = [NSTimeZone localTimeZone];
alarm.alertBody = msg;
NSLog(#"msg IS >> %#",msg);
alarm.alertAction = #"Show";
alarm.repeatInterval = 0;
alarm.soundName = UILocalNotificationDefaultSoundName;
alarm.applicationIconBadgeNumber = 1;
[app scheduleLocalNotification:alarm];
[alarm release];
}
i Hope it's helpful to you.

Resources