How to set up push notifications in Swift
Asked Answered
F

12

58

I am trying to set up a push notification system for my application. I have a server and a developer license to set up the push notification service.

I am currently running my app in Swift. I would like to be able to send the notifications remotely from my server. How can I do this?

Flotilla answered 22/7, 2014 at 22:59 Comment(0)
S
54

While the answer is given well to handle push notification, still I believe to share integrated complete case at once to ease:

To Register Application for APNS, (Include the following code in didFinishLaunchingWithOptions method inside AppDelegate.swift)


IOS 9

var settings : UIUserNotificationSettings = UIUserNotificationSettings(forTypes:UIUserNotificationType.Alert|UIUserNotificationType.Sound, categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
UIApplication.sharedApplication().registerForRemoteNotifications()

After IOS 10

Introduced UserNotifications framework:

Import the UserNotifications framework and add the UNUserNotificationCenterDelegate in AppDelegate.swift


To Register Application for APNS

let center = UNUserNotificationCenter.current()
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in

    // If granted comes true you can enabled features based on authorization.
    guard granted else { return }

    application.registerForRemoteNotifications()
}

This will call following delegate method

func application(application: UIApplication,didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
//send this device token to server
}

//Called if unable to register for APNS.
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {

println(error)

}

On Receiving notification following delegate will call:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {

    println("Recived: \(userInfo)")
   //Parsing userinfo:
   var temp : NSDictionary = userInfo
   if let info = userInfo["aps"] as? Dictionary<String, AnyObject> 
            {
                var alertMsg = info["alert"] as! String
                var alert: UIAlertView!
                alert = UIAlertView(title: "", message: alertMsg, delegate: nil, cancelButtonTitle: "OK")
                alert.show()
            }
}

To be identify the permission given we can use:

UNUserNotificationCenter.current().getNotificationSettings(){ (setttings) in

        switch setttings.soundSetting{
        case .enabled:
            print("enabled sound")

        case .disabled:
            print("not allowed notifications")

        case .notSupported:
            print("something went wrong here")
        }
    }

So the checklist of APNS:

  • Create AppId allowed with Push Notification
  • Create SSL certificate with valid certificate and app id
  • Create Provisioning profile with same certificate and make sure to add device in case of sandboxing(development provisioning)

Note: That will be good if Create Provisioning profile after SSL Certificate.

With Code:

  • Register app for push notification
  • Handle didRegisterForRemoteNotificationsWithDeviceToken method
  • Set targets> Capability> background modes> Remote Notification
  • Handle didReceiveRemoteNotification
Shellfish answered 28/5, 2015 at 14:7 Comment(6)
Thanks! It helps well specially for parsing user info.Glory
UIAlertView is deprecated. Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead.Fiord
can you please edit your answer, and show how to customise the sound with the UIAlertController ?Morph
@Morph : Share exactly, what you are looking for?Shellfish
@Arvind I'm trying to show an alert with different sound than the default sound. the sound would be from the library/sounds within the iOS system. but not matter what I do i'm getting the default sound (I know it's possible to change it from server side but I want to change it from the device since the user can choose his own sounds). now in your code I can see you create the UIAlertView, and would be nice if you can share the code to customise it as well so when the alert appears a different sound will be heard.Morph
@XcodeNOOB: Similar task I have done previously. You will need to have add sound file added into your project so that binary will contain that and need to play sound once you get the notification. You can get the sound name from notification, so that it work dynamically but for specific pre defined sounds.Shellfish
S
74

Swift 2:

let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
UIApplication.sharedApplication().registerForRemoteNotifications()
Somite answered 27/6, 2015 at 21:20 Comment(1)
no delegate call backs received ... I've tried every possible solution: network is ok, all ports are open, certificate & provisioning profile are ok, App ID is push notification capable and capabilities for Push Notifications are ON ... the weirdest thing is that the same code snippet is working fine with an objective-c project (using the same certificate, provisioning profile and internet connection) ...Gracchus
S
54

While the answer is given well to handle push notification, still I believe to share integrated complete case at once to ease:

To Register Application for APNS, (Include the following code in didFinishLaunchingWithOptions method inside AppDelegate.swift)


IOS 9

var settings : UIUserNotificationSettings = UIUserNotificationSettings(forTypes:UIUserNotificationType.Alert|UIUserNotificationType.Sound, categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
UIApplication.sharedApplication().registerForRemoteNotifications()

After IOS 10

Introduced UserNotifications framework:

Import the UserNotifications framework and add the UNUserNotificationCenterDelegate in AppDelegate.swift


To Register Application for APNS

let center = UNUserNotificationCenter.current()
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in

    // If granted comes true you can enabled features based on authorization.
    guard granted else { return }

    application.registerForRemoteNotifications()
}

This will call following delegate method

func application(application: UIApplication,didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
//send this device token to server
}

//Called if unable to register for APNS.
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {

println(error)

}

On Receiving notification following delegate will call:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {

    println("Recived: \(userInfo)")
   //Parsing userinfo:
   var temp : NSDictionary = userInfo
   if let info = userInfo["aps"] as? Dictionary<String, AnyObject> 
            {
                var alertMsg = info["alert"] as! String
                var alert: UIAlertView!
                alert = UIAlertView(title: "", message: alertMsg, delegate: nil, cancelButtonTitle: "OK")
                alert.show()
            }
}

To be identify the permission given we can use:

UNUserNotificationCenter.current().getNotificationSettings(){ (setttings) in

        switch setttings.soundSetting{
        case .enabled:
            print("enabled sound")

        case .disabled:
            print("not allowed notifications")

        case .notSupported:
            print("something went wrong here")
        }
    }

So the checklist of APNS:

  • Create AppId allowed with Push Notification
  • Create SSL certificate with valid certificate and app id
  • Create Provisioning profile with same certificate and make sure to add device in case of sandboxing(development provisioning)

Note: That will be good if Create Provisioning profile after SSL Certificate.

With Code:

  • Register app for push notification
  • Handle didRegisterForRemoteNotificationsWithDeviceToken method
  • Set targets> Capability> background modes> Remote Notification
  • Handle didReceiveRemoteNotification
Shellfish answered 28/5, 2015 at 14:7 Comment(6)
Thanks! It helps well specially for parsing user info.Glory
UIAlertView is deprecated. Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead.Fiord
can you please edit your answer, and show how to customise the sound with the UIAlertController ?Morph
@Morph : Share exactly, what you are looking for?Shellfish
@Arvind I'm trying to show an alert with different sound than the default sound. the sound would be from the library/sounds within the iOS system. but not matter what I do i'm getting the default sound (I know it's possible to change it from server side but I want to change it from the device since the user can choose his own sounds). now in your code I can see you create the UIAlertView, and would be nice if you can share the code to customise it as well so when the alert appears a different sound will be heard.Morph
@XcodeNOOB: Similar task I have done previously. You will need to have add sound file added into your project so that binary will contain that and need to play sound once you get the notification. You can get the sound name from notification, so that it work dynamically but for specific pre defined sounds.Shellfish
D
34

To register to receive push notifications via Apple Push Service you have to call a registerForRemoteNotifications() method of UIApplication.

If registration succeeds, the app calls your app delegate object’s application:didRegisterForRemoteNotificationsWithDeviceToken: method and passes it a device token.

You should pass this token along to the server you use to generate push notifications for the device. If registration fails, the app calls its app delegate’s application:didFailToRegisterForRemoteNotificationsWithError: method instead.

Have a look into Local and Push Notification Programming Guide.

Dekko answered 22/7, 2014 at 23:4 Comment(5)
registerForRemoteNotifications() is only available from iOS 8, what should we use for iOS 7?Pincenez
@JoshHarington Wasn't iOS 7 released before Swift?Impassible
@Impassible Swift supports iOS 7 by bundling the standard libraries in the app.Pituri
Remember to switch ON Push Notifications in the Target Settings -> Capabilities.Vestal
why would you use iOS7 ??Hermilahermina
B
25

registerForRemoteNotification() has been removed from ios8.

So you should use UIUserNotification

CODE EXAMPLE:

var type = UIUserNotificationType.Badge | UIUserNotificationType.Alert | UIUserNotificationType.Sound;
var setting = UIUserNotificationSettings(forTypes: type, categories: nil);
UIApplication.sharedApplication().registerUserNotificationSettings(setting);
UIApplication.sharedApplication().registerForRemoteNotifications();

Hope this will help you.

Barclay answered 31/10, 2014 at 8:9 Comment(2)
Don't forget that this works with iOS 8+ only. If you also want to support iOS 7, see https://mcmap.net/q/328781/-how-to-set-up-push-notifications-in-swiftPlymouth
FYI, this no longer works with Swift 2. For Swift 2 see @AdamWaite 's answer belowAsseveration
H
15

To support ios 8 and before, use this:

// Register for Push Notitications, if running iOS 8
if application.respondsToSelector("registerUserNotificationSettings:") {

  let types:UIUserNotificationType = (.Alert | .Badge | .Sound)
  let settings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: types, categories: nil)

  application.registerUserNotificationSettings(settings)
  application.registerForRemoteNotifications()

} else {      
  // Register for Push Notifications before iOS 8
  application.registerForRemoteNotificationTypes(.Alert | .Badge | .Sound)
}
Hiles answered 26/2, 2015 at 12:23 Comment(0)
P
14

Swift 4

I think this is the correct way for setup in iOS 8 and above.

Turn on Push Notifications in the Capabilities tab enter image description here

Import UserNotifications

import UserNotifications

Modify didFinishLaunchingWithOptions

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {


    if let notification = launchOptions?[.remoteNotification] as? [String: AnyObject] {

        // If your app wasn’t running and the user launches it by tapping the push notification, the push notification is passed to your app in the launchOptions

        let aps = notification["aps"] as! [String: AnyObject]
        UIApplication.shared.applicationIconBadgeNumber = 0
    }

    registerForPushNotifications()

    return true
}

It’s extremely important to call registerUserNotificationSettings(_:) every time the app launches. This is because the user can, at any time, go into the Settings app and change the notification permissions. application(_:didRegisterUserNotificationSettings:) will always provide you with what permissions the user currently has allowed for your app.

Copy paste this AppDelegate extension

// Push Notificaion
extension AppDelegate {
func registerForPushNotifications() {
    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
            [weak self] (granted, error) in
            print("Permission granted: \(granted)")

            guard granted else {
                print("Please enable \"Notifications\" from App Settings.")
                self?.showPermissionAlert()
                return
            }

            self?.getNotificationSettings()
        }
    } else {
        let settings = UIUserNotificationSettings(types: [.alert, .sound, .badge], categories: nil)
        UIApplication.shared.registerUserNotificationSettings(settings)
        UIApplication.shared.registerForRemoteNotifications()
    }
}

@available(iOS 10.0, *)
func getNotificationSettings() {

    UNUserNotificationCenter.current().getNotificationSettings { (settings) in
        print("Notification settings: \(settings)")
        guard settings.authorizationStatus == .authorized else { return }
        DispatchQueue.main.async {
            UIApplication.shared.registerForRemoteNotifications()
        }
    }
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    let tokenParts = deviceToken.map { data -> String in
        return String(format: "%02.2hhx", data)
    }

    let token = tokenParts.joined()
    print("Device Token: \(token)")
    //UserDefaults.standard.set(token, forKey: DEVICE_TOKEN)
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    print("Failed to register: \(error)")
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {

    // If your app was running and in the foreground
    // Or
    // If your app was running or suspended in the background and the user brings it to the foreground by tapping the push notification

    print("didReceiveRemoteNotification /(userInfo)")

    guard let dict = userInfo["aps"]  as? [String: Any], let msg = dict ["alert"] as? String else {
        print("Notification Parsing Error")
        return
    }
}

func showPermissionAlert() {
    let alert = UIAlertController(title: "WARNING", message: "Please enable access to Notifications in the Settings app.", preferredStyle: .alert)

    let settingsAction = UIAlertAction(title: "Settings", style: .default) {[weak self] (alertAction) in
        self?.gotoAppSettings()
    }

    let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)

    alert.addAction(settingsAction)
    alert.addAction(cancelAction)

    DispatchQueue.main.async {
        self.window?.rootViewController?.present(alert, animated: true, completion: nil)
    }
}

private func gotoAppSettings() {

    guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
        return
    }

    if UIApplication.shared.canOpenURL(settingsUrl) {
        UIApplication.shared.openURL(settingsUrl)
    }
}
}

Check out: Push Notifications Tutorial: Getting Started

Procure answered 23/3, 2016 at 8:5 Comment(3)
the application:didFailToRegisterForRemoteNotificationsWithError get's called if the user declines or if there's some other network kind of error or both?Herbart
show(alert: alert) and registerForPushNotifications(application) in your codes has problem I will receive these errors when I copied your app to my app Delegate class Use of unresolved identifier 'show' and Argument passed to call that takes no argumentsIndulge
need help in this question :- #52677150Fidge
S
8

Thanks for the earlier answers. Xcode has made some changes and here's the SWIFT 2 code that passes XCode 7 code check and supports both iOS 7 and above:

    if #available(iOS 8.0, *) {
        let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
        UIApplication.sharedApplication().registerUserNotificationSettings(settings)
        UIApplication.sharedApplication().registerForRemoteNotifications()
    } else {
        let settings = UIRemoteNotificationType.Alert.union(UIRemoteNotificationType.Badge).union(UIRemoteNotificationType.Sound)
        UIApplication.sharedApplication().registerForRemoteNotificationTypes(settings)
    }
Salmonoid answered 23/12, 2015 at 10:26 Comment(0)
S
2

Swift 4

Import the UserNotifications framework and add the UNUserNotificationCenterDelegate in AppDelegate

import UserNotifications

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate

To Register Application for APNS, (Include the following code in didFinishLaunchingWithOptions method inside AppDelegate.swift)

let center = UNUserNotificationCenter.current()
    center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
        // Enable or disable features based on authorization.
    }
    application.registerForRemoteNotifications()

This will call following delegate method

func application(_ application: UIApplication,didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    //send this device token to server

}

//Called if unable to register for APNS.
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    print(error)
}

On Receiving notification following delegate will call:

private func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {

    print("Recived: \(userInfo)")
    //Parsing userinfo:

}
Sirup answered 1/11, 2018 at 5:57 Comment(0)
M
1

Swift 3:

let center = UNUserNotificationCenter.current()
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
        // Enable or disable features based on authorization.
    }
UIApplication.shared.registerForRemoteNotifications()

Make sure to import UserNotifications at the top of your view controller.

import UserNotifications
Martin answered 12/7, 2017 at 17:13 Comment(0)
C
0

You can send notification using the following code snippet:

let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
if(UIApplication.sharedApplication().currentUserNotificationSettings() == settings ){
//OK
}else{
//KO
}
Chela answered 26/9, 2015 at 10:14 Comment(0)
S
0

I use this code snip in AppDelegate.swift:

let pushType = UIUserNotificationType.alert.union(.badge).union(.sound)
let pushSettings = UIUserNotificationSettings(types: pushType
            , categories: nil)

application.registerUserNotificationSettings(pushSettings)
application.registerForRemoteNotifications()
Shift answered 21/11, 2017 at 8:47 Comment(0)
O
-1

100% Working... You Can read onesignal document and setup properly https://documentation.onesignal.com/docs/ios-sdk-setup OneSignal below code import in AppDelegate

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    OneSignal.setLogLevel(.LL_VERBOSE, visualLevel: .LL_NONE)
    
    // OneSignal initialization
    let onesignalInitSettings = [kOSSettingsKeyAutoPrompt: false, kOSSettingsKeyInAppLaunchURL: false]
    
    OneSignal.initWithLaunchOptions(launchOptions,
                                    appId: "YOUR_ONE_SIGNAL_ID",
                                    handleNotificationAction: nil,
                                    settings: onesignalInitSettings)
    
    OneSignal.inFocusDisplayType = OSNotificationDisplayType.inAppAlert;
    // promptForPushNotifications will show the native iOS notification permission prompt.
    // We recommend removing the following code and instead using an In-App Message to prompt for notification permission (See step 8)
    OneSignal.promptForPushNotifications(userResponse: { accepted in
        print("User accepted notifications: \(accepted)")
    })

    return true
}
Oblige answered 11/12, 2020 at 9:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.