For Swift 3 and Swift 4.0
Using NotificationCenter and the AppDelegate method didRegister notificationSettings
. NotificationSettings show whether the users opted for badges, sounds, etc. and will be an empty array if they declined push notifications. It is fired specifically when users respond to the push notifications prompt and seems to be what most devs use, since it's more specific than checking didBecomeActive. But Apple might change this. Who knows?
Unfortunately, NotificationCenter does not have a preset notification name so you either have to setup and extension (see end) or use the raw value in (SO has more on this).
In AppDelegate:
func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
// if not registered users will have an empty set of settings
let accepted: Bool = !notificationSettings.types.isEmpty
NotificationCenter.default.post(name: Notification.Name(rawValue: "didRespondToPrompt"), object: self, userInfo: ["didAccept" : accepted])
}
Then observe wherever you need to, for example in a view controller:
class MyViewController: UIViewController {
//MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(MyViewController.didRespondToPushPrompt(_:)), name: NSNotification.Name(rawValue: "didRespondToPrompt"), object: nil)
}
@objc func didRespondToPushPrompt(_ notification: Notification) {
if let userInfo: [AnyHashable : Any] = notification.userInfo, let didAccept: Bool = userInfo[NSNotificationKeyNames.didAccept] as? Bool, !didAccept {
//if user doesn't accept, do this...
} else {
//all other situations code goes here
}
}
}
Couple of things: First, for Swift 4.0, I'm using "@objc" in front of one method, but it's not necessary for Swift 3.
Also, for using NotificationCenter, in practice I did not use "rawValue". Instead I made an extension like so:
import Foundation
extension NSNotification.Name {
static let DidRegisterForPushNotifications = NSNotification.Name("DidRegisterForPushNotifications")
}
Which I could then use like so:
NotificationCenter.default.post(name: Notification.Name.DidRegisterForPushNotifications, object: self, userInfo: ["didAccept" : myBool])
etc., etc.
UserNotifications
framework then you can find out if the user clicked yes/no using a callback. See here – Demonstrable