Richiedi l'autorizzazione dell'utente per ricevere UILocalNotifications in iOS 8


115

Ho impostato le notifiche locali nel delegato dell'app utilizzando questo:

- (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]];
}

Quando eseguo l'app e poi la chiudo ricevo un messaggio di errore che dice:

07/06/2014 11: 14: 16.663 CCA-TV [735: 149070] Tentativo di programmare una notifica locale {data del fuoco = sabato 7 giugno 2014 alle 11:14:21 Pacific Daylight Time, fuso orario = America / Los_Angeles (PDT) offset -25200 (Daylight), intervallo di ripetizione = 0, conteggio ripetizioni = UILocalNotificationInfiniteRepeatCount, data del prossimo incendio = sabato 7 giugno 2014 11:14:21 Pacific Daylight Time, informazioni utente = (null)} con un avviso ma non hanno ricevuto l'autorizzazione dall'utente per visualizzare gli avvisi

Come posso ottenere l'autorizzazione necessaria per visualizzare gli avvisi?


1
Penso che l'app abbia rifiutato l'autorizzazione una volta, puoi provare ad abilitare dalle Impostazioni. Ma a proposito UILocalNotification non necessita dell'autorizzazione dell'utente ..
iphonic

Prova registerUserNotificationSettings. Se fosse stato iOS 8, questo thread avrebbe risposto alla tua domanda. Ma guarda avanti :
stackoverflow.com/questions/24006998/…

Risposte:


237

Poiché iOS 8 è necessario chiedere l'autorizzazione dell'utente per mostrare le notifiche dalla tua app, questo vale sia per le notifiche remote / push che locali. In Swift puoi farlo in questo modo,

Aggiornamento per 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.
    }

Anche la sintassi dell'obiettivo C è molto simile.

- (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;
}

Per verificare i tipi di notifica attualmente registrati è possibile utilizzare il metodo della classe UIApplication,

- (UIUserNotificationSettings *)currentUserNotificationSettings

Quindi, se l'utente ha detto no alla tua app, questa funzione dovrebbe restituire un'impostazione senza alcun tipo in essa.

Ho scritto un tutorial su questo, puoi vederlo qui .


1
Se l'utente nega l'autorizzazione, come determinarlo successivamente in modo programmatico?
jjxtra

@satheeshwaran Quando uso questo codice, funziona bene con il simulatore con iOS8. Volevo che l'obiettivo di distribuzione della mia app iniziasse da iOS7. Così, quando si esegue questo codice su un dispositivo iOS7, ottengo questo errore: dyld: Symbol not found: _OBJC_CLASS_$_UIUserNotificationSettings. C'è un altro modo in Swift per chiedere all'utente le autorizzazioni per poter lavorare in iOS7? per favore aiuto.
Raghavendra

@Raghav UIUserNotificationSettings è disponibile solo da iOS 8 e quello che stai affrontando è il comportamento giusto. Non dovresti usarlo in iOS 7.
Satheeshwaran

1
-1 per controllare la versione iOS UIDevice. stackoverflow.com/a/25735175/1226304 la risposta ha un approccio migliore per farlo.
derpoliuk

3
@derpoliuk Aggiornato come nella risposta a vantaggio di tutti, ok ??
Satheeshwaran

38

Metti questo codice nel controller della vista dove programmerai per la prima volta le notifiche (se le programmi all'avvio, allora sarà 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))
}

Le soluzioni che eseguono il test rispetto al numero di versione del sistema non sono ottimali e sono soggette a errori.


Vorrei usare application.respondsToSelector(Selector("registerUserNotificationSettings"))eif ([application respondsToSelector:@selector(registerUserNotificationSettings:)])
derpoliuk

7
Bene, è solo perché lo stai usando all'interno application:didFinishLaunchingWithOptions:che fornisce un applicationoggetto utile :)
KPM

18

Prova questo per Objective-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];
  }
}

Per 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

Ho appena affrontato lo stesso problema. Sembra che in iOS 8 dobbiamo fare un passaggio aggiuntivo, di solito fatto all'interno:

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

Puoi usare questo codice se vuoi mantenerlo compatibile con le versioni precedenti:

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

Il sistema ricorderà la decisione e chiederà solo una volta.


Meglio controllare la versione iOS con questo codice se ([[UIDevice currentDevice] .systemVersion floatValue] <10)
Mehul Chuahan

1

** Notifica locale con azione a tre pulsanti per iOS8 +

// Pulsante: HO PRESO, RICORDO DOPO, SALTO **

        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()

        }

    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.