Thomas
Thomas

Reputation: 2386

Swift - Performing background task

I'm trying to run this code in the background when a notification is received:

window?.rootViewController?.dismissViewControllerAnimated(false, completion: nil)
NSNotificationCenter.defaultCenter().postNotificationName("ResetStatusBar", object: nil)

So I've placed this code in didReceiveRemoteNotification like so:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
    print("Remote notification received in didReceiveRemoteNotification with fetchCompletionHandler")

    // just pop to rootViewController
    window?.rootViewController?.dismissViewControllerAnimated(false, completion: nil)
    NSNotificationCenter.defaultCenter().postNotificationName("ResetStatusBar", object: nil)
}

This code executes when a notification is received when the app is active, or if the user clicks on the notification that is received, however, if I receive a notification, ignore it, and then open the app (that I did not kill, just pressed the home button on), the changes have not taken effect in the application.

Here are somethings I'm currently doing:

This is also how I'm registering for push notifications in my AppDelegate file:

let notificationSettings = UIUserNotificationSettings(forTypes: [.Alert,.Badge,.Sound], categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(notificationSettings)
UIApplication.sharedApplication().registerForRemoteNotifications()

Any ideas why my code isn't executing? Is it because it's a UI change?

P.S. here's what my push notification payload looks like:

let payload = {
  default: notificationDisplayText,
  APNS: {
    aps: {
      alert: notificationDisplayText,
      sound: 'default',
      badge: 1,
      'content-available' : 1
    },
    notificationId: notificationId
  }
}

Am I correct in putting the content-available key inside the aps object, or should I be nesting it directly inside the APNSobject?

Upvotes: 1

Views: 658

Answers (2)

Rob
Rob

Reputation: 437392

If you want to process an unhandled notification when the app starts up, you do that in didFinishLaunchingWithOptions, using .remoteNotification key in Swift 3 (UIApplicationLaunchOptionsRemoteNotificationKey in Swift 2.3) in the launchOptions dictionary.

As the documentation for application(_:didReceiveRemoteNotification:) says:

If the app is not running when a remote notification arrives, the method launches the app and provides the appropriate information in the launch options dictionary. The app does not call this method to handle that remote notification. Instead, your implementation of the application(_:willFinishLaunchingWithOptions:) or application(_:didFinishLaunchingWithOptions:) method needs to get the remote notification payload data and respond appropriately.


Unrelated, remember that in didReceiveRemoteNotification you must call completionHandler when you're done processing the notification.

As the documentation says (and the emphasis was in the original):

As soon as you finish processing the notification, you must call the block in the handler parameter or your app will be terminated. Your app has up to 30 seconds of wall-clock time to process the notification and call the specified completion handler block. In practice, you should call the handler block as soon as you are done processing the notification. The system tracks the elapsed time, power usage, and data costs for your app’s background downloads. Apps that use significant amounts of power when processing remote notifications may not always be woken up early to process future notifications.

Upvotes: 1

cmyers78
cmyers78

Reputation: 76

There are two areas in the app delegate:

If you want something to continue running the background after the user presses the home button... func applicationDidEnterBackground(_ application: UIApplication) { ...}

If you want something to happen if the user goes back into the application... func applicationDidBecomeActive(_ application: UIApplication) { ...}

so if you want something to happen in the background..such as send or receive notifications, you'll want to use appDidEnterBackground...

Upvotes: 1

Related Questions