5

I'm working on an app that gives you a notification at mid-day. This notification is supposed to be different every day.

I got the notifications themselves working:

let notificationOptions: UNAuthorizationOptions = [.alert, .sound];
UNUserNotificationCenter.current().requestAuthorization(options: notificationOptions) { (granted, error) in
    if !granted {
        print("Something went wrong")
    } else {
        let content = UNMutableNotificationContent()
        content.body = getRandomDailyString()
        content.sound = UNNotificationSound.default()

        let date = DateComponents(hour: 12, minute: 15)
        let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)

        let request = UNNotificationRequest(identifier: "Daily String", content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request) { (error) in
            if let error = error {
                print(error.localizedDescription)
            }
        }
    }
}

What's happening now is that the getRandomDailyString()-function is called, it returns a string, and a repeating notification is set which does appear the specified time, but always has the same content.

How would I go about making a notification that gives a unique content every day?

Shivam Tripathi
  • 1,405
  • 3
  • 19
  • 37
matthias_code
  • 833
  • 8
  • 21
  • 1
    Ok, got it... same line of thought but quite different. Your request is always the same in this case. you add once and it repeats. You never change the content or trigger or nothing. You should invalidate your request and add new one every each time you trigger one – GIJOW Apr 10 '18 at 15:21
  • 2
    I think the problem is the `repeats: true`, so this notification you created will be shown repeatedly. You should schedule 1 notification at a time. – henrique Apr 10 '18 at 15:40

2 Answers2

4

Cannot test it right now, but try it and tell me

If it is not inside a function I would place it in one. Then you call it from your delegate method. Don't forget to change it to not be repeatable.

You must have a class to handle its delegates methods, can be your AppDelegate or any other class you create.

Delegate UNUserNotificationCenterDelegate

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    x()
}

func x() {
    let notificationOptions: UNAuthorizationOptions = [.alert, .sound];
    UNUserNotificationCenter.current().requestAuthorization(options: notificationOptions) { (granted, error) in
        if !granted {
            print("Something went wrong")
        } else {
            let content = UNMutableNotificationContent()
            content.body = getRandomDailyString()
            content.sound = UNNotificationSound.default()

            let date = DateComponents(hour: 12, minute: 15)
            let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: false)

            let request = UNNotificationRequest(identifier: "Daily String", content: content, trigger: trigger)
            UNUserNotificationCenter.current().add(request) { (error) in
                if let error = error {
                    print(error.localizedDescription)
                }
            }
        }
    }
}

This answer can help you too

Getting local notifications to show while app is in foreground Swift 3

GIJOW
  • 2,307
  • 1
  • 17
  • 37
  • Good idea! Didn't end up working, sadly. The next notification following the current one does not end up happening – matthias_code Apr 18 '18 at 14:39
  • 1
    This solution is relevant if application is in foreground. Otherwise, the new notification will is not scheduled. Maybe using a server of Push notification from some service is the way possible. – Douglas Frari May 22 '18 at 12:28
  • 1
    Not sure why the question was downvoted. I want to do exactly this: a notification for a random "word of the day". Did you finally find a solution, @IcarusTyler? – Carmen Nov 24 '18 at 17:11
  • 2
    Thanks for checking in @Carmen! I figured out a potential solution, but it turned out to be rather complicated for what was supposed to be a simple addition to my app. It is impossible to schedule a repeating solution with a new random string daily, but it is possible to schedule up to 64 notifications (with unique content) in advance. The workaround would be to check on app-entering how many notifications are still scheduled, and then create enough new ones to have 64 scheduled ones again! :) Sadly this also means it would stop working after 64 days of not opening the app – matthias_code Nov 27 '18 at 10:07
  • Thanks for the update @IcarusTyler. In my case, I ended up abandoning the notification, and instead implementing a Today extension (widget). It's just as appropriate for my use case. – Carmen Nov 27 '18 at 12:51
  • @Carmen Sweet, I got one too! :D (maybe that was the solution all along :P ) – matthias_code Nov 27 '18 at 14:17
  • 1
    @Carmen Can you please explain how to update content body in every notification? – Siva Feb 20 '19 at 07:11
  • @Ranjani I didn't use a notification in the end. I used a Today extension instead. – Carmen Feb 20 '19 at 16:31
3

Ok, here is the solution for this.

It is NOT possible to schedule a repeating notification with a random content each day. The content is defined when the notification is scheduled, and cannot be changed later.

What you CAN do it schedule up to 64 notifications in advance though. So you can schedule 64 unique notifications for the next 64 days, and then whenever you open the app check how many remain, and fill up the notification-schedule up to 64 again.

If you don't open the app after 64 days the notifications stop coming though :P

Peter O.
  • 32,158
  • 14
  • 82
  • 96
matthias_code
  • 833
  • 8
  • 21