Fragen Sie nach der Benutzerberechtigung zum Empfangen von UILocalNotifications in iOS 8


115

Ich habe lokale Benachrichtigungen im App-Delegaten eingerichtet. Verwenden Sie dazu Folgendes:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    UILocalNotification *notification = [[UILocalNotification alloc]init];
    [notification setAlertBody:@"Watch the Latest Episode of CCA-TV"];
    [notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:5]];
    [notification setTimeZone:[NSTimeZone defaultTimeZone]];
    [application setScheduledLocalNotifications:[NSArray arrayWithObject:notification]];
}

Wenn ich die App starte und dann beende, erhalte ich die Fehlermeldung:

2014-06-07 11: 14: 16.663 CCA-TV [735: 149070] Versuch, eine lokale Benachrichtigung zu planen {Branddatum = Samstag, 7. Juni 2014, 11:14:21 Uhr pazifische Sommerzeit, Zeitzone = Amerika / Los_Angeles (PDT) Offset -25200 (Tageslicht), Wiederholungsintervall = 0, Wiederholungszahl = UILocalNotificationInfiniteRepeatCount, nächstes Feuerdatum = Samstag, 7. Juni 2014, 11:14:21 Uhr Pacific Daylight Time, Benutzerinfo = (null)} mit einer Warnung Der Benutzer hat jedoch keine Berechtigung zum Anzeigen von Warnungen erhalten

Wie kann ich die erforderliche Berechtigung zum Anzeigen der Warnungen erhalten?


1
Ich denke, die App hat die Berechtigung einmal abgelehnt, Sie können versuchen, über Einstellungen zu aktivieren. Aber übrigens braucht UILocalNotification keine Benutzererlaubnis ..
— iphonic

Versuchen Sie es registerUserNotificationSettings. Wäre es iOS 8 gewesen, hätte dieser Thread Ihre Frage beantwortet. Aber schauen Sie weiter - stackoverflow.com/questions/24006998/…
— raurora

Antworten:


237

Da Sie in iOS 8 den Benutzer um Erlaubnis bitten müssen, Benachrichtigungen von Ihrer App anzuzeigen, gilt dies sowohl für Remote- / Push- als auch für lokale Benachrichtigungen. In Swift können Sie es so machen,

Update für Swift 2.0

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
    // Override point for customization after application launch.
    if(UIApplication.instancesRespondToSelector(Selector("registerUserNotificationSettings:")))
    {
        let notificationCategory:UIMutableUserNotificationCategory = UIMutableUserNotificationCategory()
        notificationCategory.identifier = "INVITE_CATEGORY"
        notificationCategory.setActions([replyAction], forContext: UIUserNotificationActionContext.Default)

        //registerting for the notification.
        application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes:[.Sound, .Alert, .Badge], categories: nil))
    }
    else
    {
       //do iOS 7 stuff, which is pretty much nothing for local notifications.
    }
    return true
}

Swift 3.2

if(UIApplication.instancesRespond(to: #selector(UIApplication.registerUserNotificationSettings(_:)))){
     let notificationCategory:UIMutableUserNotificationCategory = UIMutableUserNotificationCategory()
     notificationCategory.identifier = "INVITE_CATEGORY"
     notificationCategory.setActions([replyAction], forContext: UIUserNotificationActionContext.Default)

     //registerting for the notification.
        application.registerUserNotificationSettings(UIUserNotificationSettings(types:[.sound, .alert, .badge], categories: nil))
}
else{
        //do iOS 7 stuff, which is pretty much nothing for local notifications.
    }

Die Ziel-C-Syntax ist ebenfalls sehr ähnlich.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]){
        [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
    }
    // Override point for customization after application launch.
    return YES;
}

Um nach aktuell registrierten Benachrichtigungstypen zu suchen, können Sie die Methode der UIApplication-Klasse verwenden.

- (UIUserNotificationSettings *)currentUserNotificationSettings

Wenn der Benutzer zu Ihrer App Nein gesagt hat, sollte diese Funktion eine Einstellung ohne Typen zurückgeben.

Ich habe ein Tutorial darüber geschrieben, könnte man es sehen hier .


1
Wie bestimmen Sie dies später programmgesteuert, wenn der Benutzer die Berechtigung verweigert?
— jjxtra

@satheeshwaran Wenn ich diesen Code verwende, funktioniert er gut mit dem Simulator mit iOS8. Ich wollte das Bereitstellungsziel meiner App ab iOS7. Wenn ich diesen Code auf einem iOS7-Gerät ausführe, wird folgende Fehlermeldung angezeigt : dyld: Symbol not found: _OBJC_CLASS_$_UIUserNotificationSettings. Gibt es in Swift eine andere Möglichkeit, Benutzer nach Berechtigungen zu fragen, um in iOS7 arbeiten zu können? Bitte helfen Sie.
— Raghavendra

@Raghav UIUserNotificationSettings ist nur unter iOS 8 verfügbar und Sie sehen sich mit dem richtigen Verhalten konfrontiert. Sie sollten dies nicht in iOS 7 verwenden.
— Satheeshwaran

1
-1 zum Überprüfen des UIDevice der iOS-Version. Die Antwort von stackoverflow.com/a/25735175/1226304 hat einen besseren Ansatz, um dies zu tun.
— derpoliuk

3
@derpoliuk Aktualisiert wie in der Antwort zum Nutzen aller, ok?
— Satheeshwaran

38

Fügen Sie diesen Code in den View Controller ein, in dem Sie zuerst die Benachrichtigungen programmieren (wenn Sie sie beim Start programmieren, ist dies der Fall application:didFinishLaunchingWithOptions:):

if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {
    [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeSound categories:nil]];
}

In Swift:

if(UIApplication.instancesRespondToSelector(Selector("registerUserNotificationSettings:"))) {
    UIApplication.sharedApplication().registerUserNotificationSettings(UIUserNotificationSettings(forTypes: .Alert | .Sound, categories: nil))
}

Die Lösungen, die anhand der Versionsnummer des Systems getestet werden, sind nicht optimal und fehleranfällig.


Ich würde application.respondsToSelector(Selector("registerUserNotificationSettings"))andif ([application respondsToSelector:@selector(registerUserNotificationSettings:)])
— derpoliuk

7
Nun, das liegt nur daran, dass Sie es im Inneren verwenden, application:didFinishLaunchingWithOptions:was ein praktisches applicationObjekt darstellt :)
— KPM

18

Versuchen Sie dies für Ziel-C:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:    (NSDictionary *)launchOptions
{
// are you running on iOS8?
if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) 
  {
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge|UIUserNotificationTypeAlert|UIUserNotificationTypeSound) categories:nil];
    [application registerUserNotificationSettings:settings];
  } 
else // iOS 7 or earlier
  {
    UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
    [application registerForRemoteNotificationTypes:myTypes];
  }
}

Für Swift:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
// Override point for customization after application launch.
 if(UIApplication.instancesRespondToSelector(Selector("registerUserNotificationSettings:")))
 {
    application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: UIUserNotificationType.Sound | UIUserNotificationType.Alert | UIUserNotificationType.Badge, categories: nil))
 }
 else
 {
    //
 }
return true
}

5

Ich hatte gerade das gleiche Problem. Scheint, als müssten wir in iOS 8 einen zusätzlichen Schritt ausführen, der normalerweise im Inneren ausgeführt wird:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { /*...*/ }

Sie können diesen Code verwenden, wenn Sie ihn abwärtskompatibel halten möchten:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
    if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)])
    {
        [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]];
    }
#endif

Das System merkt sich die Entscheidung und fragt nur einmal.


Es ist besser, die iOS-Version mit diesem Code zu überprüfen, wenn ([[UIDevice currentDevice] .systemVersion floatValue] <10)
— Mehul Chuahan

1

** Lokale Benachrichtigung mit drei Tasten für iOS8 +

// Button: Ich habe es genommen, später daran erinnert, es übersprungen **

        let completeAction = UIMutableUserNotificationAction()
        completeAction.identifier = "COMPLETE_TODO"
        completeAction.title = "I TOOK IT"
        completeAction.activationMode = .Background
        completeAction.destructive = true
        completeAction.authenticationRequired = false

        let remindAction = UIMutableUserNotificationAction()
        remindAction.identifier = "REMIND_TODO"
        remindAction.title = "REMIND LATER"
        remindAction.activationMode = .Background
        remindAction.destructive = false
        //  remindAction.authenticationRequired = false

        let skipAction = UIMutableUserNotificationAction()
        skipAction.identifier = "SKIP_TODO"
        skipAction.title = "SKIP IT"
        skipAction.activationMode = .Background
        skipAction.destructive = false
        skipAction.authenticationRequired = false


        let todoCategory = UIMutableUserNotificationCategory()
        todoCategory.identifier = "TODO_CATEGORY"
        todoCategory.setActions([completeAction, remindAction, skipAction], forContext: .Default)
        todoCategory.setActions([completeAction,remindAction,skipAction], forContext: .Minimal)


        if application.respondsToSelector("isRegisteredForRemoteNotifications")
        {

            let categories = NSSet(array: [todoCategory,todoVideoCategory])
            let types:UIUserNotificationType = ([.Alert, .Sound, .Badge])

            let settings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: types, categories: categories as? Set<UIUserNotificationCategory>)

            application.registerUserNotificationSettings(settings)
            application.registerForRemoteNotifications()

        }

    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.