Search code examples
iosobjective-cuilocalnotificationalarmhardcode

Is there a better way to compute the top of the hour code for repeat interval notification?


I have hard coded this Hour to help me fire the local notification at the top of each hour, but something is wrong. Though, I dunno if it's the way I'm testing it, my Xcode behaviour, or the code itself. Anyway, here is the code I made, have a look at it and please guide me to an easier or a better way to code such things. Thank You.

NSCalendar *calendar1 = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar1 components:(NSHourCalendarUnit |NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:[NSDate date]];
hour = [components hour];
min =[components minute];
sec =[components second];
NSLog(@"hour is %i",hour);

NSLog(@"min is %i",min);

NSLog(@"sec is %i",sec);
if (hour < 24) {
 hour=hour+1;
 } else {
     hour=0;

And then..

[[UIApplication sharedApplication] cancelAllLocalNotifications];
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar] ;
NSDateComponents *componentsForReferenceDate = [[NSDateComponents alloc] init];
[componentsForReferenceDate setHour:hour];
[componentsForReferenceDate setMinute:0];
[componentsForReferenceDate setSecond:0];

 NSDate *fireDateOfNotification = [calendar dateFromComponents: componentsForReferenceDate];

// Create the notification

Solution

  • There are a few things to take on board here:

    • When asking for the date you don't need to ask for minutes and seconds as you scrap them anyway.
    • You should probably set a timeZone
    • When the hour is 23 you will add 1, which makes 24 which is not right
    • You don't need to create a new NSDateComponents object, you can just configure the one you have

      NSCalendar *calendar = [NSCalendar currentCalendar];
      calendar.timeZone = [NSTimeZone timeZoneWithName:@"GMT"];
      
      NSDateComponents *components = [calendar components:NSHourCalendarUnit fromDate:[NSDate date]];
      components.hour   = (components.hour + 1) % 24;
      components.minute = 0;
      components.second = 0;
      
      NSDate *fireDate = [calendar dateFromComponents:components];
      NSLog(@"%@", fireDate);
      

    The use of % for setting the hour prevents us going over 23