Search code examples
iosswiftnsdatelocalnotification

How to send a localNotification at a specific time everyday, even if that time has passed?


I have this code which runs a notification everyday at 7am, it gets the current date and then runs the notification when it gets to the set hour, my problem is if the time has already passed the set run time then everyday it will run at the user current time not my time on 7am, here is my code

var dateFire: NSDateComponents = NSDateComponents()
var getCurrentYear = dateFire.year
var getCurrentMonth = dateFire.month
var getCurrentDay = dateFire.day

dateFire.year = getCurrentYear
dateFire.month = getCurrentMonth
dateFire.day = getCurrentDay
dateFire.hour = 7
dateFire.minute = 0
dateFire.timeZone = NSTimeZone.defaultTimeZone()


var calender: NSCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
var date: NSDate = calender.dateFromComponents(dateFire)!

var localNotification = UILocalNotification()
localNotification.fireDate = date
localNotification.alertBody = "A new day has begun and a fresh layer on snow lies on the mountain! Can you beat your highscore?"
localNotification.repeatInterval = NSCalendarUnit.CalendarUnitDay

UIApplication.sharedApplication().scheduleLocalNotification(localNotification)

As you can see NSCalendarUnit.CaldendarUnitDay makes it run everyday at 7am. I don't know so that even if the time is after 7am the notification will still run the next day would be greatly appreciated


Solution

  • Updated @Paulw11 's answer to Swift 3.0 and wrapped up in a function:

    /// Set up the local notification for everyday
    /// - parameter hour: The hour in 24 of the day to trigger the notification
    class func setUpLocalNotification(hour: Int, minute: Int) {
    
        // have to use NSCalendar for the components
        let calendar = NSCalendar(identifier: .gregorian)!;
    
        var dateFire = Date()
    
        // if today's date is passed, use tomorrow
        var fireComponents = calendar.components( [NSCalendar.Unit.day, NSCalendar.Unit.month, NSCalendar.Unit.year, NSCalendar.Unit.hour, NSCalendar.Unit.minute], from:dateFire)
    
        if (fireComponents.hour! > hour 
            || (fireComponents.hour == hour && fireComponents.minute! >= minute) ) {
    
            dateFire = dateFire.addingTimeInterval(86400)  // Use tomorrow's date
            fireComponents = calendar.components( [NSCalendar.Unit.day, NSCalendar.Unit.month, NSCalendar.Unit.year, NSCalendar.Unit.hour, NSCalendar.Unit.minute], from:dateFire);
        }
    
        // set up the time
        fireComponents.hour = hour
        fireComponents.minute = minute
    
        // schedule local notification
        dateFire = calendar.date(from: fireComponents)!
    
        let localNotification = UILocalNotification()
        localNotification.fireDate = dateFire
        localNotification.alertBody = "Record Today Numerily. Be completely honest: how is your day so far?"
        localNotification.repeatInterval = NSCalendar.Unit.day
        localNotification.soundName = UILocalNotificationDefaultSoundName;
    
        UIApplication.shared.scheduleLocalNotification(localNotification);
    
    }