1

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.

SergioM
  • 1,595
  • 1
  • 15
  • 27

4 Answers4

2

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

Community
  • 1
  • 1
manujmv
  • 6,450
  • 1
  • 22
  • 35
  • Thanks but that only solves the problem for the first notification, which I already do. I'm using the monthly notifications using the repeatInterval NSMonthCalendarUnit. The problem lies on how the OS schedules the following notifications, not the first one I set. Thanks. – SergioM Apr 17 '14 at 04:18
  • Thanks @manujmv. I updated the question and added some clarifications. – SergioM Apr 17 '14 at 04:54
0

-[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.

jscs
  • 63,694
  • 13
  • 151
  • 195
  • Thank for the answer. That allows me to set the first notification on a valid date of the current month, but the problem is that next month will be on the 30th again, or 28th even when the user selected 31st. – SergioM Apr 17 '14 at 04:35
  • `UILocalNotification`s are strictly interval-based, as far as I know. If you want "last day of month" functionality, I believe that you will have to re-schedule the notification every month. – jscs Apr 17 '14 at 04:42
  • Thanks Josh. I updated the question. Added some clarifications. – SergioM Apr 17 '14 at 04:53
  • If you use NSTimer for example, when the timer fires, you invalidate the timer and create a new one. Strictly speaking you should do that with daily and weekly notifications as well, because sometimes they are an hour longer or shorter than expected. – gnasher729 Apr 17 '14 at 06:46
0

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.
SergioM
  • 1,595
  • 1
  • 15
  • 27
-1

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

damithH
  • 5,148
  • 2
  • 27
  • 31
  • Thanks, that is not my problem. I have set it as a monthly notification. The problem is 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? – SergioM Apr 17 '14 at 07:03
  • check the answer. http://stackoverflow.com/questions/10739834/can-i-set-uilocalnotification-to-repeat-every-last-day-of-every-month – damithH Apr 17 '14 at 07:57