I'm scheduling a batch of notifications in my app, some with repeat intervals, others just single fires at a specific date. I'm setting my notifications using this method to create the notifications:
func notification(date: Date, repeatUnit: NSCalendar.Unit?) -> UILocalNotification {
let notification = UILocalNotification()
notification.category = "ReminderCategory"
notification.alertTitle = "Test"
notification.alertBody = "Test Body"
notification.soundName = "Sound1.m4a"
notification.fireDate = date
notification.repeatInterval = repeatUnit ?? NSCalendar.Unit(rawValue: 0)
notification.timeZone = TimeZone.init(secondsFromGMT: 0)!
return notification
}
The notifications fire at the correct times (for the local timezone) if the repeatUnit variable is set to be any of the NSCalendar.Unit units.
However, if I don't set a repeatInterval, the notifications fireDates are somehow set in the past and they fire as soon as I schedule the notifications.
Does anyone have any idea what's going on?
This works for me.
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = "Title"
content.body = "Your text"
content.categoryIdentifier = "reminder-notification"
content.sound = UNNotificationSound.default()
var dateComponents = DateComponents()
dateComponents.hour = Calendar.current.component(.hour, from: date)
dateComponents.minute = Calendar.current.component(.minute, from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
center.add(request)
Related
currently I'm working one project in swift 5. I'm trying to push local notifications on specific date & time. I have tried below code and when I set 60.0 interval then its working find but when I set specific date & time then not working.
I have searched & checked so many question but still didn't found the solution. I have checked below questions
get current date from [NSDate date] but set the time to 10:00 am
UNUserNotificationCenter Swift - Local Notification Not Firing in specific cases
let app = UIApplication.shared
let notificationSettings = UIUserNotificationSettings(types: [.alert, .sound], categories: nil)
app.registerUserNotificationSettings(notificationSettings)
let calendar = NSCalendar.current
let date = NSDateComponents()
print("before date get ::=> \(date)")
date.hour = 16
date.minute = 52
date.month = 6
date.day = 20
date.year = 2019
date.timeZone = NSTimeZone.system
print("after custom date get ::=> \(date)")
let alarm = UILocalNotification()
alarm.fireDate = calendar.date(from: date as DateComponents)
alarm.timeZone = NSTimeZone.default
alarm.alertTitle = "Data success"
alarm.alertBody = "successfuly"
alarm.soundName = "Sound.wav"
app.scheduleLocalNotification(alarm)
app.scheduleLocalNotification(alarm)
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationString(forKey: "Elon said:", arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: "Hello Tom!Get up, let's play with Jerry!", arguments: nil)
content.sound = UNNotificationSound.default
content.badge = UIApplication.shared.applicationIconBadgeNumber + 1 as NSNumber;
content.categoryIdentifier = "com.elonchan.localNotification"
// Deliver the notification in 60 seconds.
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 60.0 , repeats: false)
let request = UNNotificationRequest.init(identifier: "FiveSecond", content: content, trigger: trigger)
// Schedule the notification.
let center = UNUserNotificationCenter.current()
center.add(request)
}
I expect to set specific date & time to fire local notification.
You have to use the UNCalendarNotificationTrigger not UNTimeIntervalNotificationTrigger and UILocalNotificaion is deprecated
let mutable = UNMutableNotificationContent()
mutable.body = "message"
mutable.title = "title"
var date = DateComponents()
date.hour = 16
date.minute = 52
date.month = 6
date.day = 20
date.year = 2019
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: false)
let request = UNNotificationRequest(identifier: "key", content: mutable, trigger: trigger)
UNUserNotificationCenter.current().add(request)
This code will help you on how to send a local notification every day. You can set an hour and minute.
func setUpLocalNotification(_ hour: Int, _ minute: Int) {
print("Local Notification Setup")
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);
}
/// -> If you want to get tomorrow date you can use this code.
/*
dateFire = dateFire.tomorrow!
*/
// 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 = "alert body"
localNotification.alertTitle = "alert title"
localNotification.repeatInterval = NSCalendar.Unit.day
localNotification.soundName = UILocalNotificationDefaultSoundName;
UIApplication.shared.scheduleLocalNotification(localNotification);
}
extension Date {
var tomorrow: Date? {
return Calendar.current.date(byAdding: .day, value: 1, to: self)
}
}
I have this array it's already populated in a table view with dynamic cells, what I want it's create a local agenda or notification or alarm or something similar to remind the user to take the medicine at the day and the hour that is displayed in the array, could you help me? please. Thanks a lot.
{“medicine”:”paracetamol”
“day”:”tuesday”
“time”:”9:00”},
{“medicine”:”aspirine”
“day”:”friday”
“time”:”16:00”},
{“medicine”:”pills”
“day”:”monday”
“time”:”22:00”}
You have to create a calendar object and set your weekday and time values in comps.weekday, comps.hour and comps.minute properties.
And for your message, set in notification content.body property.
import UserNotifications
let calendar = NSCalendar.init(calendarIdentifier: .gregorian)
calendar?.locale = NSLocale.current
let year = calendar?.component(.year, from: date)
let month = calendar?.component(.month, from: date)
let cal = Calendar.current
var comps = cal.dateComponents([.weekOfYear, .yearForWeekOfYear], from: date)
comps.weekday = i // Monday - Friday
comps.hour = j
comps.minute = minute
comps.year = year
comps.month = month
let notificationDate = cal.date(from: comps)!
let interval = String.init(format: "%d%d%d", i,j,minute)
if #available(iOS 10.0, *) {
let triggerDate = Calendar.current.dateComponents([.weekday,.hour,.minute], from: notificationDate as Date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate,
repeats: true)
let content = UNMutableNotificationContent()
content.title = DataManager.sharedInstance.notificationTitle
content.body = String.init(format: "%#", DataManager.sharedInstance.notificationMessage)
content.sound = UNNotificationSound.default()
let request = UNNotificationRequest(identifier: String(interval), content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print(error)
}
}
} else {
// ios 9
// Fallback on earlier versions
let notification = UILocalNotification()
/* Time and timezone settings */
notification.fireDate = date
notification.repeatInterval = NSCalendar.Unit.weekday
notification.timeZone = NSCalendar.current.timeZone
notification.alertBody = "message"
notification.userInfo = [ "title" : String(interval)]
/* Schedule the notification */
UIApplication.shared.scheduleLocalNotification(notification)
}
UPDATED ANSWER
Convert your json to NSArray of NSDictionary objects. using NSJSonSerialisation class.
Run a for loop with the NSArray instance and access NSDictionary objects one by one.
Use NSDictionary valueForKey method. Pass the key name and get the value from dictionary.
I have recently updated my project to IOS 10, which has caused any local notifications I had registered to not fire. I have tried to convert the local notification to user notifications but it is not having the same effect. Here is the original code I tried to convert. Within viewDidLoad:
guard let settings = UIApplication.shared.currentUserNotificationSettings else { return
}
if settings.types == UIUserNotificationType() {
let ac = UIAlertController(title: "Cant Schedule", message: "No Permission", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(ac, animated: true, completion: nil)
return
}
var dateComp: DateComponents = DateComponents()
dateComp.year = 2017;
dateComp.month = 01;
dateComp.day = 28;
dateComp.hour = 11;
dateComp.minute = 0;
(dateComp as NSDateComponents).timeZone = TimeZone.current
let calender:Calendar = Calendar(identifier: Calendar.Identifier.gregorian)
let date:Date = calender.date(from: dateComp)!
let notification = UILocalNotification()
notification.fireDate = date
notification.alertBody = "Notification!"
notification.alertAction = "You just Received a notification!"
notification.soundName = UILocalNotificationDefaultSoundName
notification.userInfo = ["customField1": "w00t"]
notification.repeatInterval = NSCalendar.Unit.weekOfYear
UIApplication.shared.scheduleLocalNotification(notification)
This caused a local notification to fire at 11:00 am every saturday.
Here is the code I used to try and achieve the same effect in IOS 10:
func scheduleNotification(at date: Date) {
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents(in: .current, from: date)
let newComponents = DateComponents(calendar: calendar, timeZone: .current, month: components.month, day: components.day, hour: components.hour, minute: components.minute)
let trigger = UNCalendarNotificationTrigger(dateMatching: newComponents, repeats: true)
let content = UNMutableNotificationContent()
content.title = "Notification"
content.body = "You just Received a notification!"
content.sound = UNNotificationSound.default()
let request = UNNotificationRequest(identifier: "textNotification", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print("Error")
}
}
}
In viewDidLoad:
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) {(accepted, error) in
if !accepted {
print("Error")
}
}
This code works fine if the user selects the date using a datePicker, but I can't figure out how to programmatically set the date of the notification to the same date I had in the local notification (2017-28-01 11:00), and also how to make the notification fire every week at the same time as there is no repeatInterval property.
Could you explain how you could only specify for example Monday at 11:00 am
It's just a matter of leaving out everything that doesn't apply to the repeated value. Thus, in your case you want to specify the date components hour:11 and weekday:2 and nothing else.
To understand how this works, run this in a playground:
let dc = DateComponents(hour:11, weekday:2)
let greg = Calendar(identifier: .gregorian)
let d = greg.nextDate(after: Date(), matching: dc, matchingPolicy:.nextTime)
You will see that d is this coming Monday at 11AM.
That is exactly what UNNotificationTrigger will do to figure out when to send this notification.
Now, if you also set this to be a repeats trigger, you have just specified every Monday at 11AM.
So I'm currently building a schedule app and I'm trying to create a local notification to fire on specific time on specific day of the week, every week. So the first thing I do is get the date value of the start time of the event, then I subtract 5 minutes from the start time value and then schedule the notification. Previously it was very easy just had to type:
notification.repeatInterval = CalendarUnit.WeekOfYear but now the command is deprecated in Swift 3 and yeah, so the only way I found is:
let someMinutesEarlier = Calendar.current.date(byAdding: .minute, value: -5, to: startTimePicker.date)
let contentOfNotification = UNMutableNotificationContent()
let interval = someMinutesEarlier?.timeIntervalSinceNow
contentOfNotification.title = "Event starting"
contentOfNotification.body = "Some notes"
contentOfNotification.sound = UNNotificationSound.default()
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: interval!, repeats: true)
let request = UNNotificationRequest.init(identifier: notificationIdentifier, content: contentOfNotification, trigger: trigger)
let center = UNUserNotificationCenter.current()
center.add(request) { (error) in
print(error as Any)
}
but this only schedules the notification only once (no matter that the repeat boolean is set to true), because of the year in the someMinutesEarlier...or it's may be something else? Any idea?
As McNight mentionned, you can use UNCalendarNotificationTrigger like so:
let interval = 60 * 60 * 24 * 7 - 300 // One week minus 5 minutes.
let alarmTime = Calendar.current.date(byAdding: .second, value: interval, to: Date())!
let components = Calendar.current.dateComponents([.weekday, .hour, .minute], from: alarmTime)
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
(I haven't tested this code, but this should get you on the right path).
More information here.
Edit: Fixed time interval calculation suggested by SwiftyCruz.
Edit 2: Updated to use a Calendar to perform the time shift as suggested by RickiG.
// Swift2.3
func setLNotification(weekDay:Int , hour:Int, min:Int, second:Int, alertBody:String, type:String, isRepeate:Bool){
let calender = NSCalendar(identifier: NSCalendarIdentifierGregorian)
let dateComp: NSDateComponents?
dateComp = calender?.components([.Year,.WeekOfMonth,.Month], fromDate: NSDate())
dateComp?.hour = hour
dateComp?.minute = min
dateComp?.second = 00
dateComp?.weekday = weekDay
dateComp!.timeZone = NSTimeZone.localTimeZone()
print(calender?.dateFromComponents(dateComp!))
let SetCustomDate = calender?.dateFromComponents(dateComp!)
print(SetCustomDate)
let notification = UILocalNotification()
if isRepeate == true{
switch type {
case "Weekly":
notification.fireDate = SetCustomDate!.dateByAddingTimeInterval(60*60*24*7)
notification.repeatInterval = NSCalendarUnit.Weekday
case "2 Weekly":
notification.fireDate = SetCustomDate!.dateByAddingTimeInterval(60*60*24*14)
notification.repeatInterval = NSCalendarUnit.Day
case "Monthly":
notification.fireDate = SetCustomDate!.dateByAddingTimeInterval(60*60*24*28)
notification.repeatInterval = NSCalendarUnit.Day
default:
break;
}
notification.soundName = UILocalNotificationDefaultSoundName
notification.repeatCalendar = calender
}
notification.alertTitle = "STATS"
notification.alertBody = "Please update your Stats detail"
notification.userInfo = ["uid":"reminder"]
print(notification)
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
I want my app to notify the user everyday at 13pm. I put this inside my app delegate:
func Notification() {
var Notification = UILocalNotification()
Notification.alertAction = "New Question!"
Notification.alertBody = "Solve the new question!"
Notification.fireDate = NSDate(timeIntervalSinceNow: 0)
UIApplication.sharedApplication().scheduleLocalNotification(Notification)
}
and this inside my application didFinishLaunching:
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: UIUserNotificationType.Badge | UIUserNotificationType.Sound, categories: nil))
What do I have to do so that my notification is scheduled to fire daily?
just set any past date that at 13pm,
and set repeatInterval as .CalendarUnitDay
let startDate = Date()
var component = Calendar.current.dateComponents([.year, .month, .day, .hour], from: Date())
component.hour = 13
let fireDate = Calendar.current.date(from: component)
notification.repeatInterval = .day;
notification.fireDate = fireDate
Update:
let trigger = UNCalendarNotificationTrigger(dateMatching: component, repeats: true)
var triggerDaily = Calendar.current.dateComponents([.hour,.minute,.second], from: Date())
triggerDaily.hour = 13
triggerDaily.minute = 0
triggerDaily.second = 0
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
let content = UNMutableNotificationContent()
content.title = "title"
content.body = "body"
content.categoryIdentifier = "todoList"
let request = UNNotificationRequest(identifier: "identifier", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) {(error) in // to do }