Swift ios prüft, ob Remote-Push-Benachrichtigungen in ios9 und ios10 aktiviert sind

71

Wie kann ich überprüfen, ob der Benutzer Remote-Benachrichtigungen auf ios 9 oder ios 10 aktiviert hat?

Wenn der Benutzer Nein nicht zugelassen oder darauf geklickt hat, möchte ich eine Nachricht umschalten und fragen, ob er Benachrichtigungen aktivieren möchte.

user2636197
quelle

Antworten:

36

Diese Antwort ist veraltet und wird unter iOS 10 nicht unterstützt. Sie können diese Antwort überprüfen .


Verwenden Sie diesen Code

let isRegisteredForRemoteNotifications = UIApplication.shared.isRegisteredForRemoteNotifications
if isRegisteredForRemoteNotifications {
     // User is registered for notification
} else {
     // Show alert user is not registered for notification
}
Rajat
quelle
2
Dies scheint für iOS 10 nicht zu funktionieren. Im Simulator habe ich auf "Nicht zulassen" geklickt und dieser Code besagt immer noch, dass der Benutzer für Remote-Benachrichtigungen registriert ist.
tylerSF
Funktioniert für mich unter iOS 10. Versuchen Sie, ein tatsächliches Gerät anstelle des Simulators zu verwenden.
Justin Vallely
7
Es wird nur angezeigt, ob das Token jemals generiert wurde (das Gerät wurde registriert), nicht, ob die Benachrichtigungen blockiert wurden.
KlimczakM
Remote-Benachrichtigungen werden im iOS-Simulator nicht unterstützt. Nur lokale Benachrichtigungen
Mike Carpenter
2
Dies ist nicht die richtige Methode, um dies festzustellen. Wenn Benachrichtigungen vom Benutzer deaktiviert werden, gibt diese Eigenschaft auch bei Neustarts der Anwendung weiterhin true zurück. Dies ist seltsam, da es gegen die Dokumentation verstößt, in der es heißt: "Der von dieser Methode zurückgegebene Wert berücksichtigt die Einstellungen des Benutzers für den Empfang von Remote-Benachrichtigungen." Sie müssen überprüfen, ob der Benutzer auch Benachrichtigungen zulässt.
Masterwok
143

Apple empfiehlt, UserNotificationsFramework anstelle von gemeinsam genutzten Instanzen zu verwenden. Vergessen Sie also nicht, das UserNotificationsFramework zu importieren . Da dieses Framework in iOS 10 neu ist, ist es wirklich nur sicher, diesen Code in Apps zu verwenden, die für iOS 10 + erstellt werden

let current = UNUserNotificationCenter.current()

current.getNotificationSettings(completionHandler: { (settings) in
    if settings.authorizationStatus == .notDetermined {
        // Notification permission has not been asked yet, go for it!
    } else if settings.authorizationStatus == .denied {
        // Notification permission was previously denied, go to settings & privacy to re-enable
    } else if settings.authorizationStatus == .authorized {
        // Notification permission was already granted
    }
})

Weitere Informationen finden Sie in der offiziellen Dokumentation: https://developer.apple.com/documentation/usernotifications

Ogulcan Orhan
quelle
2
Mir scheint, dies ist die richtige Antwort ab Juli 2017.
Christian Brink
2
warum ist das nicht if if elseund if else?
Jeremy Bader
@OgulcanOrhan Ja, ich weiß, dass es funktioniert - Ich habe Ihren Code verwendet und Ihre Antwort hochgestuft, damit Sie es wissen :) - Ich wollte nur wissen, warum alle drei Bedingungen aufgerufen werden müssen. Ich bin ein bisschen pedantisch, nehme ich an
Jeremy Bader
18
Ja, ich persönlich würde mich für eine switch-Anweisung entscheiden.
C. Bess
10
Es ist erstaunlich, wie die Jungs von Apple es immer schaffen, etwas so Einfaches wie den Zugriff auf zwei Boolesche Werte zu machen, um ein Durcheinander asynchroner Anfragen zu werden. Ich bin wirklich neugierig, die Gründe für solche Entscheidungen zu kennen.
Jalone
40

Ich habe Rajats Lösung ausprobiert, aber unter iOS 10 (Swift 3) hat es bei mir nicht funktioniert. Es wurde immer gesagt, dass Push-Benachrichtigungen aktiviert waren. Unten ist, wie ich das Problem gelöst habe. Dies bedeutet "nicht aktiviert", wenn der Benutzer auf "Nicht zulassen" getippt hat oder wenn Sie den Benutzer noch nicht gefragt haben.

let notificationType = UIApplication.shared.currentUserNotificationSettings!.types
    if notificationType == [] {
        print("notifications are NOT enabled")
    } else {
        print("notifications are enabled")
    }

PS: Die Methode currentUserNotificationSettingswar in iOS 10.0 veraltet, funktioniert aber immer noch.

tylerSF
quelle
Funktioniert dies unter iOS 9,8,7 usw. oder benötige ich separaten Code?
Cam Connor
Ich bin nicht sicher, ich habe es nur auf iOS 10 überprüft.
tylerSF
3
Cam, ich habe diesen Code gerade auf 10.2 (auf einem Telefon) und auf 9.3 (auf dem Simulator) getestet und es hat auf beiden funktioniert. tylerSF, danke für die lösung.
KeithB
1
Diese Lösung ist besser, da sie auch den Fall verwaltet, in dem Benutzer Einstellungen vornehmen, Benachrichtigungen
aktivieren
6
'currentUserNotificationSettings' war in iOS 10.0 veraltet: Verwenden Sie UserNotifications Frameworks - [UNUserNotificationCenter getNotificationSettingsWithCompletionHandler:] und - [UNUserNotificationCenter getNotificationCategoriesWithCompletionHandler:]
Dot Freelancer
33

Wenn Ihre App iOS 10 und iOS 8, 9 unterstützt, verwenden Sie den folgenden Code

// At the top, import UserNotifications 
// to use UNUserNotificationCenter
import UserNotifications

Dann,

if #available(iOS 10.0, *) {
    let current = UNUserNotificationCenter.current()
    current.getNotificationSettings(completionHandler: { settings in

        switch settings.authorizationStatus {

        case .notDetermined:
            // Authorization request has not been made yet
        case .denied:
            // User has denied authorization.
            // You could tell them to change this in Settings
        case .authorized:
            // User has given authorization.
        }
    })
 } else {
     // Fallback on earlier versions
     if UIApplication.shared.isRegisteredForRemoteNotifications {
         print("APNS-YES")
     } else {
         print("APNS-NO")
     }
 }
Imtee
quelle
18

in iOS11, Swift 4 ...

 UNUserNotificationCenter.current().getNotificationSettings { (settings) in
        if settings.authorizationStatus == .authorized {
            // Already authorized
        }
        else {
            // Either denied or notDetermined
            UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
                (granted, error) in
                  // add your own 
                UNUserNotificationCenter.current().delegate = self
                let alertController = UIAlertController(title: "Notification Alert", message: "please enable notifications", preferredStyle: .alert)
                let settingsAction = UIAlertAction(title: "Settings", style: .default) { (_) -> Void in
                    guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
                        return
                    }
                    if UIApplication.shared.canOpenURL(settingsUrl) {
                        UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                        })
                    }
                }
                let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
                alertController.addAction(cancelAction)
                alertController.addAction(settingsAction)
                DispatchQueue.main.async {
                    self.window?.rootViewController?.present(alertController, animated: true, completion: nil)

                }
            }
        }
    }
Joel Prithivi
quelle
Ich bekomme eine FehlermeldungUse of unresolved identifier 'UNUserNotificationCenter'; did you mean 'NSNotificationCenter'?
ChrisO
2
@ ChrisO müssen Sie UserNotifications
Faipdeoiad
10

@ Rajats Antwort ist nicht genug.

  • isRegisteredForRemoteNotifications Wenn Ihre App eine Verbindung zu APNS hergestellt hat und ein Gerätetoken erhält, kann dies für eine stille Push-Benachrichtigung sein
  • currentUserNotificationSettings ist für Benutzerberechtigungen vorgesehen. Ohne diese Berechtigung werden keine Warn-, Banner- oder Sound-Push-Benachrichtigungen an die App gesendet

Hier ist der Scheck

static var isPushNotificationEnabled: Bool {
  guard let settings = UIApplication.shared.currentUserNotificationSettings
    else {
      return false
  }

  return UIApplication.shared.isRegisteredForRemoteNotifications
    && !settings.types.isEmpty
}

Für iOS 10 currentUserNotificationSettingssollten Sie das UserNotificationsFramework verwenden , anstatt nach zu suchen

center.getNotificationSettings(completionHandler: { settings in
  switch settings.authorizationStatus {
  case .authorized, .provisional:
    print("authorized")
  case .denied:
    print("denied")
  case .notDetermined:
    print("not determined, ask user for permission now")
  }
})

Push-Benachrichtigungen können auf viele Arten an unsere Apps gesendet werden, und wir können darum bitten

UNUserNotificationCenter.current()
  .requestAuthorization(options: [.alert, .sound, .badge])

Der Benutzer kann jederzeit zur App Einstellungen gehen und diese deaktivieren. Überprüfen Sie dies daher am besten im settingsObjekt

open class UNNotificationSettings : NSObject, NSCopying, NSSecureCoding {


    open var authorizationStatus: UNAuthorizationStatus { get }


    open var soundSetting: UNNotificationSetting { get }

    open var badgeSetting: UNNotificationSetting { get }

    open var alertSetting: UNNotificationSetting { get }


    open var notificationCenterSetting: UNNotificationSetting { get }
}
onmyway133
quelle
2
Beachten Sie, dass dies ab iOS 10
Yuchen Zhong
7

Hier ist eine Lösung zum Abrufen einer Zeichenfolge, die die aktuelle Berechtigung beschreibt, die mit iOS 9 über iOS 11 mit Swift 4 funktioniert. Diese Implementierung verwendet When für Versprechen.

import UserNotifications

private static func getNotificationPermissionString() -> Promise<String> {
    let promise = Promise<String>()

    if #available(iOS 10.0, *) {
        let notificationCenter = UNUserNotificationCenter.current()
        notificationCenter.getNotificationSettings { (settings) in
            switch settings.authorizationStatus {
            case .notDetermined: promise.resolve("not_determined")
            case .denied: promise.resolve("denied")
            case .authorized: promise.resolve("authorized")
            }
        }
    } else {
        let status = UIApplication.shared.isRegisteredForRemoteNotifications ? "authorized" : "not_determined"
        promise.resolve(status)
    }

    return promise
}
Oscar Apeland
quelle
5

Obwohl der Benutzer die Push-Benachrichtigungen nicht zulässt, ist das Geräte-Token verfügbar. Daher ist es auch eine gute Idee, zu überprüfen, ob Push-Benachrichtigungen empfangen werden dürfen .

private func checkPushNotificationAllowed(completionHandler: @escaping (Bool) -> Void) {
    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().getNotificationSettings { (settings) in
            if settings.authorizationStatus == .notDetermined || settings.authorizationStatus == .denied {
                completionHandler(false)
            }
            else {
                completionHandler(true)
            }
        }
    }
    else {
        if let settings = UIApplication.shared.currentUserNotificationSettings {
            if settings.types.isEmpty {
                completionHandler(false)
            }
            else {
                completionHandler(true)
            }
        }
        else {
            completionHandler(false)
        }
    }
}
Joey
quelle
4
class func isRegisteredForRemoteNotifications() -> Bool {
    if #available(iOS 10.0, *) {
        var isRegistered = false
        let semaphore = DispatchSemaphore(value: 0)
        let current = UNUserNotificationCenter.current()
        current.getNotificationSettings(completionHandler: { settings in
            if settings.authorizationStatus != .authorized {
                isRegistered = false
            } else {
                isRegistered = true
            }
            semaphore.signal()
        })
        _ = semaphore.wait(timeout: .now() + 5)
        return isRegistered
    } else {
        return UIApplication.shared.isRegisteredForRemoteNotifications
    }
}
Debaprio B.
quelle
3
Bitte tun Sie dies nicht, damit eine asynchrone Operation synchron erscheint -> _ = semaphore.wait (Zeitüberschreitung: .now () + 5)
Augie
@Augie Gibt es einen bestimmten Grund, außer dass der asynchrone Vorgang in einigen seltenen Fällen länger als 5 Sekunden dauern kann?
ViruMax
2

für iOS12 und Swift 4 unterstützen auch iOS13 und Swift5 Ich habe auch einen Git dafür erstellt, den Sie hier überprüfen können

Fügen Sie diese Singleton-Datei einfach in Ihr XCode-Projekt ein

import Foundation
import UserNotifications


class NotificaionStatusCheck {


    var window: UIWindow?

    private var currentViewController : UIViewController? = nil


     static let shared = NotificaionStatusCheck()

    public func currentViewController(_ vc: UIViewController?) {
        self.currentViewController = vc
        checkNotificationsAuthorizationStatus()
    }


    private func checkNotificationsAuthorizationStatus() {
        let userNotificationCenter = UNUserNotificationCenter.current()
        userNotificationCenter.getNotificationSettings { (notificationSettings) in
            switch notificationSettings.authorizationStatus {
            case .authorized:
                print("The app is authorized to schedule or receive notifications.")

            case .denied:
                print("The app isn't authorized to schedule or receive notifications.")
                self.NotificationPopup()
            case .notDetermined:
                print("The user hasn't yet made a choice about whether the app is allowed to schedule notifications.")
                self.NotificationPopup()
            case .provisional:
                print("The application is provisionally authorized to post noninterruptive user notifications.")
                self.NotificationPopup()
            }
        }

    }

    private func NotificationPopup(){
        let alertController = UIAlertController(title: "Notification Alert", message: "Please Turn on the Notification to get update every time the Show Starts", preferredStyle: .alert)
        let settingsAction = UIAlertAction(title: "Settings", style: .default) { (_) -> Void in
            guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
                return
            }
            if UIApplication.shared.canOpenURL(settingsUrl) {
                UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                })
            }
        }
        let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
        alertController.addAction(cancelAction)
        alertController.addAction(settingsAction)
        DispatchQueue.main.async {
            self.currentViewController?.present(alertController, animated: true, completion: nil)

        }

    }


}

Um auf diesen Code im ViewController-Benutzer zuzugreifen, klicken Sie auf viewDidLoad

NotificaionStatusCheck.shared.currentViewController(self)
Vishal Shelake
quelle
Für den Fall, dass notDetermineddie Berechtigung noch nicht angefordert wurde. Wozu also den Benutzer an die Einstellungen senden? Es sollte in diesem Fall um Erlaubnis bitten.
Jzeferino
0

Alle Antworten sind über fast richtig , aber wenn Sie Push - Benachrichtigungen aktiviert haben und alle Optionen deaktiviert (alertSetting, lockScreenSetting etc.), authorizationStatuswird authorizedund Sie keine Push - Benachrichtigungen nicht erhalten.

Der beste Weg, um herauszufinden, ob Ihr Benutzer Remote-Benachrichtigungen erhalten kann, besteht darin, alle diese Einstellungswerte zu überprüfen. Sie können dies mit Erweiterungen erreichen.

Hinweis: Diese Lösung funktioniert für iOS 10+. Wenn Sie ältere Versionen unterstützen, lesen Sie bitte die vorherigen Antworten.

extension UNNotificationSettings {

    func isAuthorized() -> Bool {
        guard authorizationStatus == .authorized else {
            return false
        }

        return alertSetting == .enabled ||
            soundSetting == .enabled ||
            badgeSetting == .enabled ||
            notificationCenterSetting == .enabled ||
            lockScreenSetting == .enabled
    }
}
extension UNUserNotificationCenter {

    func checkPushNotificationStatus(onAuthorized: @escaping () -> Void, onDenied: @escaping () -> Void) {
        getNotificationSettings { settings in
            DispatchQueue.main.async {
                guard settings.isAuthorized() {
                    onDenied()
                    return
                }

                onAuthorized()
            }
        }
    }
}
Mateusz
quelle