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

4

5

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

Heavensent answered 5/8, 2015 at 0:2 Comment(1)
You need to check the current time - if it is after 7:00 set the fire date to tomorrow, not today.Fusspot
R
7

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);

}
Rickie answered 30/12, 2016 at 15:14 Comment(2)
Can that message be changed every day based on data that the app gathers?Auberge
WOULD YOU LIKE TO ANSWER THIS PLZ #49666518Including
H
14

Swift 5.1
This one for example fires every day at 8:00 A.M. :

let notificationContent = UNMutableNotificationContent()
notificationContent.title = "Title"
notificationContent.body = "This is a test"
notificationContent.badge = NSNumber(value: 1)
notificationContent.sound = .default
                
var datComp = DateComponents()
datComp.hour = 8
datComp.minute = 0
let trigger = UNCalendarNotificationTrigger(dateMatching: datComp, repeats: true)
let request = UNNotificationRequest(identifier: "ID", content: notificationContent, trigger: trigger)
                UNUserNotificationCenter.current().add(request) { (error : Error?) in
                    if let theError = error {
                        print(theError.localizedDescription)
                    }
                }
Hetaerism answered 19/1, 2020 at 13:19 Comment(3)
Wherever you want ... you can wire it to a button , wrap it into a function, etc.Hetaerism
Just switch print(theError as! String) to print(theError.localizedDescription) and it's perfect!Carryingon
@MumtazHussain I feel your pain. Rarely ever does a stackoverflow answer for an iOS question specify where to actually place the code.Phebephedra
R
7

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);

}
Rickie answered 30/12, 2016 at 15:14 Comment(2)
Can that message be changed every day based on data that the app gathers?Auberge
WOULD YOU LIKE TO ANSWER THIS PLZ #49666518Including
F
4

You need to check the current hour and if it is later than 6:59 you need to schedule your notification for tomorrow - this will prevent your notification from being scheduled in the past -

var calendar: NSCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
var dateFire=NSDate()

var fireComponents=calendar.components(NSCalendarUnit.CalendarUnitDay|NSCalendarUnit.CalendarUnitMonth|NSCalendarUnit.CalendarUnitYear|NSCalendarUnit.CalendarUnitHour|NSCalendarUnit.CalendarUnitMinute, fromDate:dateFire)

if (fireComponents.hour >= 7) {
    dateFire=dateFire.dateByAddingTimeInterval(86400)  // Use tomorrow's date

    fireComponents=calendar.components(NSCalendarUnit.CalendarUnitDay|NSCalendarUnit.CalendarUnitMonth|NSCalendarUnit.CalendarUnitYear|NSCalendarUnit.CalendarUnitHour|NSCalendarUnit.CalendarUnitMinute, fromDate:dateFire)
}


fireComponents.hour = 7
fireComponents.minute = 0

dateFire = calendar.dateFromComponents(fireComponents)!

var localNotification = UILocalNotification()
localNotification.fireDate = dateFire
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)
Fusspot answered 5/8, 2015 at 0:45 Comment(2)
When I add this, it says that CalendarUnit has no member of CalendarUnitDayKarlotta
Is this with Swift 3?Fusspot
K
4

Updated version (Swift 2.0)

    let calendar: NSCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
    var dateFire=NSDate()

    var fireComponents=calendar.components([.Month, .Day, .Hour, .Minute], fromDate:NSDate())

    if (fireComponents.hour == 7) {
        dateFire=dateFire.dateByAddingTimeInterval(86400)  // Use tomorrow's date

        fireComponents=calendar.components([.Month, .Day, .Hour, .Minute], fromDate:NSDate())
    }


    fireComponents.hour = 7
    fireComponents.minute = 0

    dateFire = calendar.dateFromComponents(fireComponents)!

    let localNotification = UILocalNotification()
    localNotification.fireDate = dateFire
    localNotification.alertBody = "Don't forget to visit Quote Daily to receive daily motivation."
    localNotification.repeatInterval = NSCalendarUnit.Day

    UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
Karlotta answered 16/7, 2016 at 0:27 Comment(2)
Updated version of what?Bellerophon
Using swift 2.0 @Bellerophon , When using the answer above, you encounter problems on the lines that use: (NSCalendarUnit.CalendarUnitDay|NSCalendarUnit.CalendarUnitMonth|NSCalendarUnit.CalendarUnitYear|NSCalendarUnit.CalendarUnitHour|NSCalendarUnit.CalendarUnitMinute, fromDate:dateFire) , instead of this, you have to insert: var fireComponents=calendar.components([.Month, .Day, .Hour, .Minute], fromDate:NSDate())Karlotta

© 2022 - 2024 — McMap. All rights reserved.