Search code examples
iosuitableviewuilocalnotificationreloaddata

Reload table view in real time


The app receives a UILocalNotification, but if the user is at the UITableViewController at the fire time, the table view (containing the scheduled notifications) does not reload. The user has to get out of that view and load the view again so that the cells are loaded and, as the notification was already fired, it will not be displayed on any cell of that table view.

Problem is: If the user touches the specific tableView cell that contained the notification that just fired, the app crashes, cause the notification is not there anymore.

I've implemented the - (void)reloadData in every place possible, and it still doesn't load in real time.

What would be a better solution for this?

Other detail, how can I push a specific view after the notification is displayed (when the user slides the app icon when the phone is locked)?

Any help will be truly appreciated, since theres are the last details remaining to publish my first App.


Solution

  • The problem you describe is caused by the current local notification: While the notification is handled, it is still in the list of scheduled notifications, so refreshing the table view will have no effect. A solution to this problem is to defer reloading the table view until after the notification is handled, something like

    // In your app delegate
    - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.localNotificationsController reloadDataIfNeeded];
        });
    }
    
    // In your controller that shows the local notifications
    - (void)reloadDataIfNeeded
    {
        if (![self isViewLoaded]) return;
    
        [self.tableView reloadData];
    }
    

    You could also delete the notification from the list if you only use notifications that only fire once (so that you are sure that the notification will disappear anyway):

    // In your app delegate
    - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
    {
        [application cancelLocalNotification:notification];
        [self.localNotificationsController reloadDataIfNeeded];
    }
    

    As to the second part of your question ("how can I push a specific view after the notification is displayed (when the user slides the app icon when the phone is locked?"), there are two scenarios how an application can be activated by a local notification.

    1. Your application was suspended, but still in memory. Then selecting the local push notification will make the app enter the foreground, -application:didReceiveLocalNotification: will be called, and [application applicationState] will be UIApplicationStateInactive
    2. Your application is not running, i.e. not suspended, not in memory. Then you will receive the local notification in the launchOptions in -application:didFinishLaunchingWithOptions::

      UILocalNotification *localNotification = [launchOptions valueForKey:UIApplicationLaunchOptionsLocalNotificationKey];
      

      Despite what the documentation says, -application:didReceiveLocalNotification: will not be called in this case.

    So to show the notification that woke up the application, you can push your controller in these two cases.