I Know, This may be [duplicate question][1]. I tried so many solutions but no one solution meet my expectation. Here is my scenario.
Notification StartDate: 26-July-2022
Today's Date: 23-July-2022
I want to set a repeat Local notification from a certain start date.
Here is my Code :
func scheduleLocalNotification(startDate: Date) {
var calendar = Calendar.current
calendar.timeZone = TimeZone.current
let content = UNMutableNotificationContent()
content.title = "REMINDER For Yoga"
content.body = "Hi! Get ready for Daily Yoga Class."
content.categoryIdentifier = "Yoga_872"
let components = calendar.dateComponents([.hour, .minute], from: startDate)
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
let identifier = "Yoga_Class(222)"
let notificationRequest = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
// Add Request to User Notification Center
UNUserNotificationCenter.current().add(notificationRequest) { (error) in
if let error = error {
print("Add Notification Request Error: (\(error), \(error.localizedDescription))")
}
}
}
This code is firing notification from today not from Start date (26-July-2022).
[1]: Set repeat Local notification from date
Related
The use case is that there is a form where a user can say: I want to get a notification on X days (e.g Monday, Friday and Sunday) at 14:00. The application is in react native but I'm just calling a native swift function to schedule the notification:
import Foundation
import UserNotifications
#objc(Reminders)
class Reminders: NSObject {
#objc func setReminder(
_ message: NSString,
daysV days: NSArray,
hourV hour: NSInteger,
minuteV minute: NSInteger
) {
// We'll replace all scheduled notifications entirely
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
// Create a notification for each day that has been passed
let daysC: [Int] = days.map { $0 as! Int }
for day in daysC {
var date = DateComponents()
date.weekday = day
date.hour = hour
date.minute = minute
let content = UNMutableNotificationContent()
content.title = "Reminder"
content.body = message as String
let userCalendar = Calendar(identifier: .iso8601)
let dateTime = userCalendar.date(from: date)
let triggerDate = Calendar.current.dateComponents([.weekday,.hour,.minute], from: dateTime as! Date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: true)
let identifier = "TMWTE\(day)"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
let center = UNUserNotificationCenter.current()
center.add(request, withCompletionHandler: { (error) in
if let error = error {
print(error);
}
})
}
}
}
What I'm trying to do is get each of the weekday included in a list sent from JS and schedule a notification for it. So if the user selects Monday and Wednesday the array will be [1,3] and I'll schedule a notification for each day respectively.
What's actually happening however is that I get X notifications at once in the first day. Thus if the user selects all days then in the next triggerDate I'll get 7 notifications.
Being a complete novice in Swift I may be doing something irrational, but I cannot figure it out at the moment. Now I've also tried to set the date.day to be the next Saturday, Sunday etc.. but that causes no notifications to be shown, which makes me think that I'm missing something basic here.
Thanks!
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)
I tried to repeat a notification with UNCalendarNotificationTrigger(dateMatching:, repeats:), but this method can only repeat at a certain time.
I also tried UNTimeIntervalNotificationTrigger(timeInterval:, repeats:) and repeated a notification by a time interval, but this method could not set the start time of push notification.
And these two methods seems that there is no place to set a time for end push notifications.
I want to start with a special time and repeat notifications at regular intervals. What should I do?
Rather than using the repeats parameter you could loop from your start time to end time scheduling individual notifications.
let notifIDPrefix = "mynotif"
let notifCategory = "com.mydomain.mynotif" // this should have been registered with UNUserNotificationCenter
func scheduleNotifs(from startDate: Date, to endDate: Date, with interval: TimeInterval) {
var curDate = startDate
var count: Int = 0
while curDate.compare(endDate) != .orderedDescending {
scheduleNotif(with: "\(notifIDPrefix)_\(count)", date: curDate)
curDate = curDate.addingTimeInterval(interval)
count += 1
}
}
private func scheduleNotif(with identifier: String, date: Date) {
let content = UNMutableNotificationContent()
content.title = "My Title"
content.body = " "
content.categoryIdentifier = notifCategory
content.sound = UNNotificationSound.default()
let triggerTime = Calendar.current.dateComponents([.year, .day, .hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerTime, repeats: false)
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
let center = UNUserNotificationCenter.current()
center.add(request) { (error : Error?) in
if let theError = error {
print(theError.localizedDescription)
}
}
}
The following would schedule 3 notifications (1, 2, and 3 minutes from now).
let startDate = Date().addingTimeInterval(60)
let endDate = startDate.addingTimeInterval(60 * 2)
let interval: TimeInterval = 60
scheduleNotifs(from: startDate, to: endDate, with: interval)
I want to show local notifications to user between selected hours from user and repeat that notification for every half hour till the limit of the selected hour comes and also repeat this notification daily.
I have used this code
let components = calendar.dateComponents(in: .current, from: date)
var triggerDate = DateComponents()
triggerDate.hour = components.hour
triggerDate.minute = components.minute
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: true)
But this only repeats the notification daily at that specific time selected by user but I want to repeat this also at every half hour from that specific time.I have used UNNotifications.Any help will be much appreciated.Thanks
If you want to show local notifications for every half hour between selected hours then you have to set different notification for every hour with different notification identifier as:
var dateStart = "Pass Your Start Date for Notification."
let dateEnd = "Pass Your End Date for Notification."
//Check Start Date is less then End Date is not.
while dateStart < dateEnd {
dateStart = dateStart.addingTimeInterval(0.5 * 60 * 60) //Add half an hour to start time
//Schedule notification With body and title.
scheduleNotification(at: dateStart, body: "Show Me", titles: "Remainder")
}
Implement Notification by following function as:
//Schedule Notification with Daily bases.
func scheduleNotification(at date: Date, body: String, titles:String) {
let triggerDaily = Calendar.current.dateComponents([.hour,.minute,.second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
let content = UNMutableNotificationContent()
content.title = titles
content.body = body
content.sound = UNNotificationSound.default()
content.categoryIdentifier = "todoList"
let request = UNNotificationRequest(identifier: "NotificationAt-\(date))", 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)")
}
}
}
Pass start Date in dateStart variable and Date End Date in dateEnd variable.
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)
}
}
}