14

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:

enter image description here

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.

Community
  • 1
  • 1
ar_shabazov
  • 398
  • 1
  • 4
  • 13
  • Possible duplicate of [iOS Notification Trigger: fortnightly and/or quarterly](https://stackoverflow.com/questions/41441124/ios-notification-trigger-fortnightly-and-or-quarterly) – mfaani Jul 12 '17 at 16:12
  • Also see [How I can set a notification which UserNotifications Framework](https://stackoverflow.com/questions/38252389/how-i-can-set-a-notification-which-usernotifications-framework) – mfaani Jul 12 '17 at 16:12
  • Did you manage to create a notification for multiple weekdays? Or does it have to be created separately? @Gideon – KarenAnne Sep 15 '17 at 02:49
  • After some extensive research I only found that you have to do them separately for each weekday, or you could create a daily notification. But maybe you can, and I didn't do enough research. Nonetheless, as far as I know, you have to do them separately. If, however, you manage to find the way to do a single notification for multiple weekdays, please let me know. – ar_shabazov Sep 15 '17 at 11:33
  • hey @ar_shabazov, do you still have the code of this reminder? I'm doing same thing right now, and I'd like to have a look at how you implemented weekday saving – Bootuz May 02 '22 at 19:13

2 Answers2

26

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.

Nikhlesh Bagdiya
  • 4,316
  • 1
  • 19
  • 29
  • 2
    In the picture that I included in my question, it can be seen that user can select several days of week to repeat a single notification, for instance repeating notification on both Wednesday and Friday. So in order for a single notification to repeat for more than one day in a week, do I need to create separate notification for each day of weak, and if so is it possible to use the same identifier for more than one notification? – ar_shabazov Jul 12 '17 at 17:31
  • Yes you have to create separate notification for each day of a week and identifier should be unique for every notification, If you use the same identifier when scheduling a new notification, the system removes the previously scheduled notification with that identifier and replaces it with the new one. – Nikhlesh Bagdiya Jul 12 '17 at 17:51
  • 3
    I am not entirely sure about the use of components.weekdayOrdinal, could you please explain? I've looked it up, but still not sure about its use here. – ar_shabazov Jul 13 '17 at 12:57
  • weekdayOrdinal returns the ordinal number of weekday units for the receiver, where weekday ordinal units are 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. Here use of weekdayOrdinal is optional. – Nikhlesh Bagdiya Jul 13 '17 at 14:30
  • scheduleNotification have to call only one time or every time? – Yogesh Patel Jul 19 '22 at 06:49
11
 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)
                }
            }
       }
Ahmet Sina Ustem
  • 1,090
  • 15
  • 32
Rushikesh Welkar
  • 143
  • 1
  • 2
  • 8