12

I've built an application for iPhone using Swift and Xcode 6, and the Parse framework to handle services.

While following the Parse tutorials on how to set up push notifications, the instructions advised that I put the push notifications in the App Delegate file.

This is the code that I have added to the App Delegate file...

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var pushNotificationsController: PushNotificationController?


    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

         // Register for Push Notifications
        self.pushNotificationsController = PushNotificationController()

        if application.respondsToSelector("registerUserNotificationSettings:") {
            println("registerUserNotificationSettings.RegisterForRemoteNotificatios")
            let userNotificationTypes: UIUserNotificationType = (.Alert | .Badge | .Sound)
            let settings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: userNotificationTypes, categories: nil)
            application.registerUserNotificationSettings(settings)
            application.registerForRemoteNotifications()
        }

        return true;
    }

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

So what happens is that as soon as the application is launched for the first time, the user is prompted to grant these permissions.

What I want to do, is only prompt for these permissions after a certain action has taken place (ie, during a walkthrough of the features of the app) so I can provide a little more context on why we would want them to allow push notifications.

Is it as simple as just copying the below code in the relevant ViewController where I will be expecting to prompt the user?

// In 'MainViewController.swift' file

func promptUserToRegisterPushNotifications() {
        // Register for Push Notifications
        self.pushNotificationsController = PushNotificationController()

        if application.respondsToSelector("registerUserNotificationSettings:") {
            println("registerUserNotificationSettings.RegisterForRemoteNotificatios")
            let userNotificationTypes: UIUserNotificationType = (.Alert | .Badge | .Sound)
            let settings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: userNotificationTypes, categories: nil)
            application.registerUserNotificationSettings(settings)
            application.registerForRemoteNotifications()
        }
}

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

thanks!

Simon
  • 2,065
  • 3
  • 21
  • 28
  • 3
    Yep, you can simply move that code to be executed at the appropriate time :) – SomeGuy Jun 13 '15 at 09:29
  • thanks SomeGuy! Will try it as soon as i get back to my project and report back if I need any more assistance. Thanks! – Simon Jun 13 '15 at 09:54
  • 2
    How do you get the application: UIApplication into another viewController? – denislexic Oct 13 '15 at 22:17
  • Hey, would you mind accepting my answer if it helped? :) – LinusGeffarth Oct 29 '15 at 20:20
  • 1
    @denislexic, what I did was declared a global variable i the viewController such as `let application: UIApplication = UIApplication.sharedApplication()`. This seemed to have worked for me. :) – Simon Nov 24 '15 at 08:59

3 Answers3

9

The answer is simple. If you want the user to be prompted some other time, for instance on a button press then simply move the code regarding the request into that function (or call promptUserToRegisterPushNotifications() from somewhere else).

To get a hold of the application variable outside the AppDelegate, simply do this:

let application = UIApplication.shared

Hope that helps :)

LinusGeffarth
  • 27,197
  • 29
  • 120
  • 174
  • 1
    Thanks Linus. :) I'm away at my PC at the moment to try this, and it is what I assumed, so thanks for the clarification. :) will try it and report with feedback! Thanks! – Simon Jun 13 '15 at 09:52
  • Hi Linus, believe it or not, Im only coming to implementing this solution now. So I did as you suggested and moved the `promptUserToRegisterPushNotifications ()` method to a different view controller, but now Im getting the problem as Denislexic above brought up.. how do I reference the `application : UIApplication` to save the settings to in my MainViewController.swift file? – Simon Nov 23 '15 at 20:24
  • No problem ;) Ahm why don't you just put the whole `promptUserToRegisterPushNotifications()` method into your MainVC? – LinusGeffarth Nov 23 '15 at 20:44
  • 1
    i did do that, but in the method there is a `if application.respondsToSelector("registerUserNotificationSettings:")` that my MainVC knows nothing about the `application`. Im not sure if I need to declare an instance of the `application` in the MainVC? If so, how? – Simon Nov 23 '15 at 21:34
  • 2
    cool, so I found the solution to the 'application' problem. I just, in my MainViewController, declared an `application` variable like `let application: UIApplication = UIApplication.sharedApplication()`. This solved my problem. :) Thanks Linus! – Simon Nov 24 '15 at 08:56
  • Yeah that's how I would have done it too. Sorry, didn't have time to support you. Glad you made it though :) – LinusGeffarth Nov 24 '15 at 09:02
3

This is for Swift 2. I have placed promptUserToRegisterPushNotifications() in MainViewController.swift, but I have left didRegisterForRemoteNotificationsWithDeviceToken in AppDelegate because it didn't work when I place it on the same MainViewController.swift.

// In 'MainViewController.swift' file
func promptUserToRegisterPushNotifications() {
    // Register for Push Notifications

    let application: UIApplication = UIApplication.sharedApplication()

    if application.respondsToSelector(#selector(UIApplication.registerUserNotificationSettings(_:))) {
        print("registerUserNotificationSettings.RegisterForRemoteNotificatios")

        let notificationSettings = UIUserNotificationSettings(
            forTypes: [.Badge, .Sound, .Alert], categories: nil)
        application.registerUserNotificationSettings(notificationSettings) // Register for Remote Push Notifications
        application.registerForRemoteNotifications()
    }
}


// In AppDelegate
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
    let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
    var tokenString = ""

    for i in 0..<deviceToken.length {
        tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
    }

    NSUserDefaults.standardUserDefaults().setObject(tokenString, forKey: "deviceToken")

    print("Device Token:", tokenString)

}
Marie Amida
  • 556
  • 1
  • 5
  • 14
1

This is method I have written in the code and works fine once it called on launch (didFinishLaunch)

class func registerNotification() {
    if #available(iOS 10.0, *) {
        // push notifications
        UNUserNotificationCenter.current().requestAuthorization(options: [.sound, .alert, .badge]) {
            (granted, error) in
            if (granted) {
                UIApplication.shared.registerForRemoteNotifications()
            }
        }

        let center  = UNUserNotificationCenter.current()
        center.delegate = AppManager.appDel()
        center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
            if error == nil {
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    } else {
        UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
        UIApplication.shared.registerForRemoteNotifications()
    }
}
Prakash Raj
  • 1,943
  • 1
  • 15
  • 13