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.
Related
I want to schedule a notification to be fired twice a week:
let gregorian = Calendar(identifier: .gregorian)
let now = Date()
[2, 4].forEach { day in
let content = UNMutableNotificationContent()
content.title = "Notif title"
content.body = "Comment"
content.sound = .default
var components = gregorian.dateComponents([.year, .month, .weekdayOrdinal, .day, .hour, .minute, .second], from: now)
components.hour = 11
components.minute = 25
components.second = 0
components.weekdayOrdinal = day
let date = gregorian.date(from: components)!
let triggerDaily = gregorian.dateComponents([.weekdayOrdinal, .hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
let request = UNNotificationRequest(identifier: "test", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
if let error = error {
print("Oops: \(error)")
} else {
print("Notification created!")
}
}
}
But instead of being fired once on monday and once on wednesday, it gets called two times each day.
What am I doing wrong? Thanks for your help.
because of foreach loop your code schedule two notification with the same identifier. while your code is getting execute the 2nd loop cycle overwrite the request.
I did some R&D and refine your code a bit. On my side, it works perfectly.
Please try the code mention below.
func setNotification() {
let days = [2,4]
func ScheduleNotification(index:Int){
let calendarComponents = NSDateComponents()
calendarComponents.hour = 11
calendarComponents.minute = 25
calendarComponents.second = 0
calendarComponents.weekday = days[index]
let content = UNMutableNotificationContent()
content.title = "Notification title"
content.body = "your message here."
content.sound = UNNotificationSound.default
let trigger = UNCalendarNotificationTrigger(dateMatching: calendarComponents as DateComponents, repeats: true)
let identifier = "UYLLocalNotification\(days[index])"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in
if let error = error {
print(error)
}else{
if index == 0{
ScheduleNotification(index: 1)
}
}
})
}
ScheduleNotification(index: 0)
}
call this function in your viewdidLoad method like.
self.setNotification()
i hope it will save your time.
Simply change the name of identifier of each notification inside the foreach(_:) to something like test2, test4, i.e.
[2, 4].forEach {
let content = UNMutableNotificationContent()
content.title = "title"
content.body = "body"
content.sound = .default
var components = DateComponents()
components.timeZone = TimeZone.current
components.weekday = 11
components.hour = 25
components.minute = 0
components.second = $0
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
let request = UNNotificationRequest(identifier: "test\($0)", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
if let error = error {
print("Oops: \(error)")
} else {
print("Notification created!")
}
}
}
You can use .weekday instead of .weekdayOrdinal . According to Apple document
.weekday = A weekday or count of weekdays.
.weekdayOrdinal = weekday ordinal or count of weekday ordinals.
Weekday ordinal units represent the position of the weekday within the
next larger calendar unit, such as the month. For example, 2 is the
weekday ordinal unit for the second Friday of the month.
Try this
let triggerDate = Calendar.current.dateComponents([.weekday,.hour,.minute], from: date as Date)
triggerDat.weekday = day[index]
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate,
repeats: true)
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'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)
I am trying to schedule local notifications for specific days of week (e.g. Monday, Wednesday and etc) and then repeat them weekly.
This is how the screen for setting notifications looks:
User can select time for the notification and repeating days.
My method for scheduling single non repeating notification looks like this:
static func scheduleNotification(reminder: Reminder) {
// Setup notification content.
let content = UNMutableNotificationContent()
//content.title = NSString.localizedUserNotificationString(forKey: "Reminder", arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: reminder.reminderMessage, arguments: nil)
content.sound = UNNotificationSound.default()
// Configure the triger for specified time.
//
let dateComponentes = reminder.dateComponents
// TODO: Configure repeating alarm
// For the testing purposes we will not repeat the reminder
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponentes, repeats: false)
// Create the request object.
let request = UNNotificationRequest(identifier: "\(reminder.reminderId)", content: content, trigger: trigger)
// Schedule the request.
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.add(request) { (error: Error?) in
if let theError = error {
print(theError.localizedDescription)
}
}
}
The date components are extracted from UIDatePicker widget and stored in reminder class:
let date = reminderTimeDatePicker.date.addingTimeInterval(60 * 60 * 24 * 7)
let components = Calendar.current.dateComponents([.weekday, .hour, .minute], from: date)
...
reminder.dateComponents = components
I have an array selectedDays[Int] (as a property of reminder class) to hold info on days of week on which the notification should fire.
How can I schedule notification on specific day of week and how to repeat it weekly?
Even a single comment will be helpful, and thank you in advance.
You can use below function to get Date from selected picker value:
//Create Date from picker selected value.
func createDate(weekday: Int, hour: Int, minute: Int, year: Int)->Date{
var components = DateComponents()
components.hour = hour
components.minute = minute
components.year = year
components.weekday = weekday // sunday = 1 ... saturday = 7
components.weekdayOrdinal = 10
components.timeZone = .current
let calendar = Calendar(identifier: .gregorian)
return calendar.date(from: components)!
}
//Schedule Notification with weekly bases.
func scheduleNotification(at date: Date, body: String, titles:String) {
let triggerWeekly = Calendar.current.dateComponents([.weekday,.hour,.minute,.second,], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerWeekly, repeats: true)
let content = UNMutableNotificationContent()
content.title = titles
content.body = body
content.sound = UNNotificationSound.default()
content.categoryIdentifier = "todoList"
let request = UNNotificationRequest(identifier: "textNotification", content: content, trigger: trigger)
UNUserNotificationCenter.current().delegate = self
//UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print("Uh oh! We had an error: \(error)")
}
}
}
After getting a value from picker pass picker hour, minute and year with selected week day as (Sunday = 1, Monday = 2, Tuesday = 3, Wednesday = 4, thursday = 5, Friday = 6, Saturday = 7) to function func createDate(weekday: Int, hour: Int, minute: Int, year: Int) to get notification fire date on weekly bases, and after getting date call function func scheduleNotification(at date: Date, body: String, titles:String) for schedule a notification.
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationString(forKey: "Wake up!", arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: "Rise and shine! It's morning time!",
arguments: nil)
content.categoryIdentifier = "TIMER_EXPIRED"
let weekdaySet = [6,5]
for i in weekdaySet {
var dateInfo = DateComponents()
dateInfo.hour = 16
dateInfo.minute = 44
dateInfo.weekday = i
dateInfo.timeZone = .current
let trigger = UNCalendarNotificationTrigger(dateMatching: dateInfo, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
center.add(request) { (error : Error?) in
if let theError = error {
print(theError.localizedDescription)
}
}
}
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 }