2
var data = {
    alert: "Your driver is here!",
        sound: "ding.caf"
        session_id: session.sessionId
    }
    parse.Push.send({
        channels: ['user_id-2'],
            data: data
    },{

I'm sending a push notification with alert. When the app is in background, it works fine – I receive the alert.

However, when my app is in the foreground, a UIAlertView still pops up, and it's very jarring to the user when they're using it and suddenly an alert pops up.

How do I disable this when the app is in foreground state? This is my entire code in Swift. I'd still like access to the JSON, though.

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    let center = NSNotificationCenter.defaultCenter()

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        UIApplication.sharedApplication().idleTimerDisabled = true
        Parse.setApplicationId("SOMEID", clientKey: "SOMEKEY")
        // Register for Push Notitications
        if application.applicationState != UIApplicationState.Background {
            // Track an app open here if we launch with a push, unless
            // "content_available" was used to trigger a background push (introduced in iOS 7).
            // In that case, we skip tracking here to avoid double counting the app-open.

            let preBackgroundPush = !application.respondsToSelector("backgroundRefreshStatus")
            let oldPushHandlerOnly = !self.respondsToSelector("application:didReceiveRemoteNotification:fetchCompletionHandler:")
            var noPushPayload = false;
            if let options = launchOptions {
                noPushPayload = options[UIApplicationLaunchOptionsRemoteNotificationKey] != nil;
            }
            if (preBackgroundPush || oldPushHandlerOnly || noPushPayload) {
                PFAnalytics.trackAppOpenedWithLaunchOptionsInBackground(launchOptions, block: nil)
            }
        }
        if application.respondsToSelector("registerUserNotificationSettings:") {
            let userNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound
            let settings = UIUserNotificationSettings(forTypes: userNotificationTypes, categories: nil)
            application.registerUserNotificationSettings(settings)
            application.registerForRemoteNotifications()
        } else {
            let types = UIRemoteNotificationType.Badge | UIRemoteNotificationType.Alert | UIRemoteNotificationType.Sound
            application.registerForRemoteNotificationTypes(types)
        }
        return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
        let installation = PFInstallation.currentInstallation()
        installation.setDeviceTokenFromData(deviceToken)
        installation.saveInBackground()
    }

    func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
        if error.code == 3010 {
            println("Push notifications are not supported in the iOS Simulator.")
        } else {
            println("application:didFailToRegisterForRemoteNotificationsWithError: %@", error)
        }
    }

    func application(application: UIApplication, didReceiveRemoteNotification data: [NSObject : AnyObject]) {
        PFPush.handlePush(data)
        var dat = JSON(data)

        println("dat") //yes, we got a notification. this alerts even in foreground, which it shouldn't.

        if application.applicationState == UIApplicationState.Inactive {
            println("Inactive - this never prints")
            PFAnalytics.trackAppOpenedWithRemoteNotificationPayloadInBackground(data, block:nil)
        }
    }
rickerbh
  • 9,731
  • 1
  • 31
  • 35
TIMEX
  • 259,804
  • 351
  • 777
  • 1,080

1 Answers1

4

The didReceiveRemoteNotification delegate method is called if

  1. The user is in the application when the notification is received, or
  2. The user engages a notification after receiving it outside the app.

You can choose how to handle the notification using application.applicationState, which you have done. From How to respond to push notification view if app is already running in the background:

You can tell whether your app was just brought to the foreground or not in application:didReceiveRemoteNotification: using this bit of code:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    if ( application.applicationState == UIApplicationStateActive )
        // app was already in the foreground
    else
        // app was just brought from background to foreground
    ...
}

"Inactive" doesn't print because UIApplicationStateInactive (UIApplicationState.Inactive) is the case when the following is true:

The app is running in the foreground but is not receiving events. This might happen as a result of an interruption or because the app is transitioning to or from the background. Source

So, what you're actually looking for is UIApplicationState.Background:

if application.applicationState == UIApplicationState.Background {
    PFAnalytics.trackAppOpenedWithRemoteNotificationPayloadInBackground(data, block:nil)
}

So, that solves the open from background issue, but what about when the user receives the notification in the app? You don't want the jarring popup, so the way to disable that is to get rid of its source, PFPush.handlePush().

All that handlePush: does is create that alert view and present it to the user, so removing it will not affect anything else:

A default handler for push notifications while the app is active that could be used to mimic the behavior of iOS push notifications while the app is backgrounded or not running.
Source

That's it – just remove it and there will be no alert view.

If you want to increment the badge count, you still can:

if userInfo.objectForKey("badge") {
    let badgeNumber: Int = userInfo.objectForKey("badge").integerValue
    application.applicationIconBadgeNumber = badgeNumber
}
Community
  • 1
  • 1
AstroCB
  • 12,337
  • 20
  • 57
  • 73
  • Do I ever need to check for notifications in application:didFinishLaunchingWithOptions ? The parse documentation says I need to deal with that as well. – TIMEX Apr 12 '15 at 05:54
  • @TIMEX Only if you want to configure what happens to the user after they open your app through the push notification. See https://www.parse.com/questions/didreceiveremotenotification-didfinishlaunchingwithoptions and https://www.parse.com/questions/load-a-specific-viewcontroller-from-push-notification-slide-to-view. – AstroCB Apr 12 '15 at 06:20
  • but I thought your first part of the code solved it? I was able to get the push notification information using this: ```if ( application.applicationState == UIApplicationStateActive ) // app was already in the foreground else // app was just brought from background to foreground``` – TIMEX Apr 12 '15 at 06:33
  • @TIMEX I believe you can do it either way. – AstroCB Apr 12 '15 at 06:43