10

I want to run some code to update the viewcontroller when my local notification has been sent out, I have tried the function didReceiveLocalNotification, but it only works when the user clicks on the notification, I was wondering if there was a way to run a function when the notification has been sent out?

Victor Sigler
  • 23,243
  • 14
  • 88
  • 105
Ludvig Sørensen
  • 397
  • 4
  • 13

3 Answers3

7

I think there is no way you can know when your local notification is sent out mainly because you can schedule your local notification or send it right away in case of your app are in background.

According to Apple:

You schedule a local notification by calling scheduleLocalNotification:. The app uses the fire date specified in the UILocalNotification object for the moment of delivery. Alternatively, you can present the notification immediately by calling the presentLocalNotificationNow: method.

Apps might also find local notifications useful when they run in the background and some message, data, or other item arrives that might be of interest to the user. In this case, an app can present the notification immediately using the UIApplication method presentLocalNotificationNow: (iOS gives an app a limited time to run in the background).

There is no way to know when the UILocalNotification was sent, but it when it has received is some case of course. In your case I suppose you're scheduling a UILocalNotification so let's divided by parts:

  • The notification is delivered when the app isn’t open and the user touch it

    The delegate for an iOS app implements the application:didFinishLaunchingWithOptions: method to handle a local notification. It gets the associated UILocalNotification object from the launch-options dictionary using the UIApplicationLaunchOptionsLocalNotificationKey key. So you can know where the app was open by touching the UILocalNotification. See the following code:

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    
        if let launchNotification = launchOptions?[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification {
            // do anything you want update UIViewController, etc
        }
    
        return true
    } 
    
  • The notification is delivered when the app is running and the user touch it

    Once the user touch the UILocalNotification you can handle it using the didReceiveLocalNotification method and do whatever you want inside it.

  • The notification is delivered when the app is running and the user don't touch it

In case the user don't touch the UILocalNotification the only thing you can do to know if your UILocalNotification was sent is keep a list with the UILocalNotifications you have scheduled before and check it later(this is not a excellent solution but its work).

Nevertheless always exist the UIApplicationWillEnterForegroundNotification that can be used to notify the UIViewController you want to update that the app will enter in foreground like in this way:

private var foregroundNotification: NSObjectProtocol!

override func viewDidLoad() {
    super.viewDidLoad()

    foregroundNotification = NSNotificationCenter.defaultCenter().addObserverForName(UIApplicationWillEnterForegroundNotification, object: nil, queue: NSOperationQueue.mainQueue()) {
        [unowned self] notification in

        print("Notified ViewControllerB")
    }
}

deinit {
    // make sure to remove the observer when this view controller is dismissed/deallocated

    NSNotificationCenter.defaultCenter().removeObserver(foregroundNotification)
}

I think you have to think properly what you need to do inside you app when your notification is received in case of the user don't tap it.

I hope this help you.

Victor Sigler
  • 23,243
  • 14
  • 88
  • 105
  • Thank you so much, i think i'm so close to updating the view when the user does not tap on the notification but enters the app after the notification is sent. But it seems that i get "Notified ViewControllerB" every time i open the app, and not only after a notification. I think it is because it's not deinit-ting correctly or in the right place in my app. – Ludvig Sørensen Feb 12 '16 at 08:01
  • @LudvigSørensen No, if the `UIViewController` is still is memory you'll be notified about it, is only that. – Victor Sigler Feb 12 '16 at 15:47
  • ohh okay. I am building this daily challenge app, where a user will get a daily challenge and then be able to complete it. The function i want to run right after the notification has been sent is a fetch new challenge function, so that the view will update and give the user a new challenge. But the only problem is that when I run that function in the code you've given me, the view updates every time the user re enters the app. And i only want to update the view when a new challenge arrives. (every day) – Ludvig Sørensen Feb 12 '16 at 22:03
  • Btw: the reason I want to update the view, is because when a user click "done" on a challenge it takes them to a view where there is a countdown to the new challenge, and then the idea was that when a user re enters the app after a notification (when the countdown has reached 0) has been sent, the view will update. Thank you so much for your help :) – Ludvig Sørensen Feb 12 '16 at 22:03
  • @LudvigSørensen When the countdown has reached 0 you can save some state inside your app to the next time the user enter inside your `UIViewController` you update the app, remember that `viewWillAppear` only is executed once when the `UIViewController` is added to the hierarchy, for this is what it serve you the `UIApplicationWillEnterForegroundNotification`, for in case you enter to the app and your `UIViewController` has added to the hierarchy previously. – Victor Sigler Feb 12 '16 at 22:36
  • Thank you so much. I haven't written the countdown function yet. But I should use NSTimer for the countdown right? :) – Ludvig Sørensen Feb 12 '16 at 23:07
  • Be careful `NSTimer` don't work when your app goes to background, only for a limited time defined by Apple, you should save the time when the app go to background and then when enter take the difference and update the `NSTimer` or any other countdown. – Victor Sigler Feb 12 '16 at 23:11
  • Okay thanks :) Do you know a alternative timer that works in the background? – Ludvig Sørensen Feb 12 '16 at 23:12
  • See my answer here http://stackoverflow.com/questions/31764477/using-nstimer-to-play-sound-at-set-intervals-not-working-in-background-xcode6-4/31764874#31764874 – Victor Sigler Feb 12 '16 at 23:14
  • Thank you, now I would just need calculate the time that the user spent in the background? – Ludvig Sørensen Feb 12 '16 at 23:20
  • Yes, Just save time we left and when you enter calculate the difference between both and it is the value – Victor Sigler Feb 12 '16 at 23:21
  • Thank you again so much for your help :) – Ludvig Sørensen Feb 12 '16 at 23:22
  • I just browsed around google and stackoverflow, and found this ("http://stackoverflow.com/questions/33113638/swift-countdown-timer-labels-for-days-hours-minutes-seconds") do you think using NSCalendar would work just as great for my purpose? – Ludvig Sørensen Feb 12 '16 at 23:26
  • Is NSCalendar the way? – Ludvig Sørensen Feb 12 '16 at 23:27
  • I will :) But is NSCalendar the way or would NSTimer be a better choice? – Ludvig Sørensen Feb 12 '16 at 23:29
  • 1
    @LudvigSørensen `NSCalendar` is better to calculate the difference between two `NSDates`, `NSTimer` it's not for the same purpose, `NSTimer` it's just for set a timer nothing more you can do with it. – Victor Sigler Feb 12 '16 at 23:32
1

There is a method for this in objective c, you can search for the similar for swift.. Add this method in your appdelegate

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
       willPresentNotification:(UNNotification *)notification
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions UNNotificationPresentationOptionBadge))completionHandler{
       [self.tableview reloadData];
}

I think this will help..

Akshatha S R
  • 1,237
  • 1
  • 15
  • 30
  • This "Asks the delegate how to handle a notification that arrived while the app was running in the foreground." – MattyG May 06 '19 at 03:21
-3

You can do your updates from the method you are using to send the notification.

Beyond 2021
  • 133
  • 1
  • 7