Question

I have a notification system in my app that allows users to set multiple notifications and they can be:

  • Daily
  • Weekly
  • Monthly

The first 2 are ok, but on the third one I have a problem. Lets say that we are on March and the user sets the notification to trigger on the 31st of the month. The notification is scheduled correctly, but if we where on April (30 days) for example the notification is scheduled on the 1st of May.

I have 2 questions:

  • How can I schedule notification on the last day of the month? Or set them up to handle this case gracefully in the following months.
  • If the notification on the 31st of March is scheduled correctly, will the next one be scheduled on the 30th of April and then on the 31st of May? My guess is no, will be 31 of march, 1st April and 31st of April.

Scheduling multiple notification is not an option for me because apple has a limit and that limit can be reached easily if the user has 6 monthly notifications (6x12) and they could have more than that.

Thanks,

Sergio

EDIT

Sorry I didn't explained myself properly. I don't have the problem setting the notification on the correct day. But I have a problem with how the repetitions will work. If I set a notification to trigger on the 31st every month starting on the 31st of March (lets assume we are in March) the first one will come up on the right day, but what would happen on April?

Thanks again.

Was it helpful?

Solution 3

What I had to do was: Check if the current month has the day that the user requested (max 31).

  • If it doesnt then schedule a normal notification for the current month on the last day and then schedule the monthly one on the following month, the OS will handle the rest.

Note: If the current month doesn't have the requested day (31 of feb), the next one will definitely have it (31 of mar).

  • If it does then schedule the monthly on the current month.

OTHER TIPS

You can get the last day of the month of a specific date using the below methods

-(NSDate*)lastDayOfMonthOfDate:(NSDate *)date
{
    NSInteger dayCount = [self numberOfDaysInMonthCountForDate:date];

    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

    [calendar setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];

    NSDateComponents *comp = [calendar components:
                              NSYearCalendarUnit |
                              NSMonthCalendarUnit |
                              NSDayCalendarUnit fromDate:date];

    [comp setDay:dayCount];

    return [calendar dateFromComponents:comp];
}

-(NSInteger)numberOfDaysInMonthCountForDate:(NSDate *)date
{
    NSCalendar *calendar = [[NSCalendar alloc]   initWithCalendarIdentifier:NSGregorianCalendar];

   [calendar setTimeZone:[NSTimeZone timeZoneWithName:TIMEZONE]];

    NSRange dayRange = [calendar rangeOfUnit:NSDayCalendarUnit
                                      inUnit:NSMonthCalendarUnit
                                     forDate:date];

    return dayRange.length;
}

Find the last day from these method and schedule notification for that day

Source : Getting the last day of a month

-[NSCalendar rangeOfUnit:inUnit:forDate:] will tell you the minimum and maximum values that a particular date component can take in a larger component, in the context of a particular date.

If you use NSDayCalendarUnit and NSMonthCalendarUnit, the length of the result will be the last day of the month containing the passed date.

For example:

NSCalendar * c = [NSCalendar currentCalendar];
NSRange aprilRanger = [c rangeOfUnit:NSDayCalendarUnit 
                              inUnit:NSMonthCalendarUnit 
                             forDate:[NSDate date]];

NSLog(@"%lu", aprilRanger.length);

NSDateComponents * minusTwoMonths = [NSDateComponents new];
[minusTwoMonths setMonth:-2];
NSDate * febDay = [c dateByAddingComponents:minusTwoMonths 
                                  toDate:[NSDate date] 
                                 options:0];
NSRange febRange = [c rangeOfUnit:NSDayCalendarUnit 
                           inUnit:NSMonthCalendarUnit 
                          forDate:febDay];

NSLog(@"%lu", febRange.length);

Produces:

30
28

And this will give you the correct answer when weird things like leap days happen, too.

Hey It's not a big deal.

In your notification object set repeatInterval to NSMonthCalendarUnit

UILocalNotification *notify = [ [UILocalNotification alloc] init ];
notify.fireDate = notificationDate;
notify.repeatInterval = NSMonthCalendarUnit;
// use NSDayCalendarUnit, NSWeekCalendarUnit for daily or weekly respectively.

Thanks damithH

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top