cdub
cdub

Reputation: 25701

Triggering a weekly notification in swift 3 using local notifications api

I want to trigger a weekly notification that goes on Mondays at 7:00pm.

I see code like this:

let triggerWeekly = Calendar.current.dateComponents([.weekday, .hour, .minute, .second], from: date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerWeekly, repeats: true)
  1. What should I set the from date as?
  2. Also does the date need to be in the present?

I am using iOS 10+ and swift 3.

Upvotes: 0

Views: 1514

Answers (4)

Vidhi Patel
Vidhi Patel

Reputation: 641

You can set weekday and time in DateComponents you can receive notification for every monday at 7:00 PM and also set Repeat = "true"

func setupNotificationReminder() {
        let title:String = "Your reminder text goes here"
        var calendarComponents = DateComponents()
        calendarComponents.weekday = 2
        calendarComponents.hour = 19
        calendarComponents.second = 0
        calendarComponents.minute = 0

        // create a corresponding local notification
        let trigger = UNCalendarNotificationTrigger(dateMatching: calendarComponents, repeats: true)
        let content = UNMutableNotificationContent()
        content.title = title
        content.body = "body"
        content.sound = UNNotificationSound.default()
        content.categoryIdentifier = "YourApp"

        let request = UNNotificationRequest(identifier: "NotificationAtGivenTime", content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request) {(error) in
            if let error = error {
                print("Uh oh! We had an error: \(error)")
            }
        }
    }

Upvotes: 1

Evince Development
Evince Development

Reputation: 347

I have used below extension for Date:

extension Date {

    static func today() -> Date {
        return Date()
    }

    func next(_ weekday: Weekday, considerToday: Bool = false) -> Date {
        return get(.Next,
                   weekday,
                   considerToday: considerToday)
    }

    func previous(_ weekday: Weekday, considerToday: Bool = false) -> Date {
        return get(.Previous,
                   weekday,
                   considerToday: considerToday)
    }

    func get(_ direction: SearchDirection,
             _ weekDay: Weekday,
             considerToday consider: Bool = false) -> Date {

        let dayName = weekDay.rawValue

        let weekdaysName = getWeekDaysInEnglish().map { $0.lowercased() }

        assert(weekdaysName.contains(dayName), "weekday symbol should be in form \(weekdaysName)")

        let searchWeekdayIndex = weekdaysName.index(of: dayName)! + 1

        let calendar = Calendar(identifier: .gregorian)

        if consider && calendar.component(.weekday, from: self) == searchWeekdayIndex {
            return self
        }

        var nextDateComponent = DateComponents()
        nextDateComponent.weekday = searchWeekdayIndex


        let date = calendar.nextDate(after: self,
                                     matching: nextDateComponent,
                                     matchingPolicy: .nextTime,
                                     direction: direction.calendarSearchDirection)

        return date!
    }

}

This can be used for getting any next or previous weekday from the reference date. You'll need to get the next Monday first and then set the UNCalendarNotificationTrigger as below:

    var triggerDaily = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: Date().next(Date.Weekday.monday, considerToday: true))
    triggerDaily.hour = 19
    triggerDaily.minute = 0
    triggerDaily.second = 0


    if #available(iOS 10.0, *) {
        let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
        let content = UNMutableNotificationContent()
        content.title = "Title"
        content.body = "Body"
        content.sound = UNNotificationSound.default()
        content.categoryIdentifier = "Test"

        let request = UNNotificationRequest(identifier: "NotificationAt-\(String(describing: Calendar.current.date(from: triggerDaily))))", content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request) {(error) in
            if let error = error {
                print("Uh oh! We had an error: \(error)")
            }else {
                UNUserNotificationCenter.current().getPendingNotificationRequests(completionHandler: { (arrayRequests) in
                    for request in arrayRequests {
                        if let calendarNotificationTrigger = request.trigger as? UNCalendarNotificationTrigger,
                            let nextTriggerDate = calendarNotificationTrigger.nextTriggerDate()  {
                            print("nextTriggerDate ===>>> \(nextTriggerDate)")
                        }

                        print("Request ===>>> \(String(describing: request.trigger))")
                    }


                })
            }
        }
    } else {
        // Fallback on earlier versions
    }

The Output of this will be as below:

nextTriggerDate ===>>> 2018-07-02 13:30:00 +0000

Request ===>>> Optional( Calendar Year: 2018 Month: 7 Day: 2 Hour: 19 Minute: 0 Second: 0, repeats: YES>)

Upvotes: 1

Hardik Bar
Hardik Bar

Reputation: 1760

Pass date which you want to generate local notification

            let strDate = (data as AnyObject).value(forKey: "not_date") as? String
            let dateformatter = DateFormatter()
            dateformatter.dateFormat = "yyyy-MM-dd hh:mm a"
            let notidate = dateformatter.date(from: strDate!)

you need to first stattnotificationdate like = 2018-06-25 07:00 PM after you need to add time interval

var dateStart = Date() 
dateStart = dateStart.addingTimeInterval(TimeInterval(604800))

and generate notification with these interwal

//MARK:- Schedule Notification with Daily bases.
        func scheduleNotification(at date: Date, body: String, titles:String) {
            let triggerDaily = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date)

            if #available(iOS 10.0, *) {
                let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
                let content = UNMutableNotificationContent()
                content.title = titles
                content.body = body
                content.sound = UNNotificationSound.default()
                content.categoryIdentifier = "HardikBar"

                let request = UNNotificationRequest(identifier: "NotificationAt-\(date))", content: content, trigger: trigger)
                UNUserNotificationCenter.current().add(request) {(error) in
                    if let error = error {
                        print("Uh oh! We had an error: \(error)")
                    }
                }
            } else {
                // Fallback on earlier versions
            }

        }

Upvotes: 3

Prashant Tukadiya
Prashant Tukadiya

Reputation: 16436

Another overload of trigger required TimeInterval

So you can get

let timeInterval = dateOfNotification.timeIntervalSinceNow

Now

let trigger = UNTimeIntervalNotificationTrigger(timeInterval: timeInterval, repeats: true)

You can create date as

   if let date = Calendar.current.date(byAdding: .day, value: 7, to: self) {
      let date1 = Calendar.current.date(bySettingHour: hours, minute: minutes, second: 00, of: date)        
   }

If you want specific day then refer https://stackoverflow.com/a/49561764/4601900

Upvotes: 0

Related Questions