Попросіть дозволу користувача на отримання UILocalNotifications в iOS 8


115

Я налаштував місцеві сповіщення в Делегат додатків, використовуючи це:

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

Коли я запускаю програму, а потім закриваю її, я отримую помилку:

2014-06-07 11: 14: 16.663 CCA-TV [735: 149070] Спроба запланувати місцеве сповіщення {дата пожежі = субота, 7 червня 2014 року о 11:14:21 Тихоокеанський літній час, часовий пояс = Америка / Лос_Ангелес (PDT) зміщення -25200 (денне світло), інтервал повторів = 0, кількість повторень = UILocalNotificationInfiniteRepeatCount, наступна дата загорання = субота, 7 червня 2014 р. В 11:14:21 Тихоокеанський літній час, інформація про користувача = (null)} з попередженням але не отримали від користувача дозволу на показ сповіщень

Як я можу отримати необхідний дозвіл для відображення сповіщень?


1
Я думаю, що додаток один раз відхилив дозвіл, ви можете спробувати ввімкнути налаштування. Але до речі UILocalNotification не потребує дозволу користувача ..
iphonic

Спробуйте registerUserNotificationSettings. Якби це було iOS 8, ця тема відповіла б на ваше запитання. Але, г вперед подивимося - stackoverflow.com/questions/24006998 / ...
raurora

Відповіді:


237

Оскільки в iOS 8 вам потрібно запитати дозволу користувача на показ сповіщень із вашого додатка, це стосується як віддалених / push-так, так і локальних сповіщень. У Swift ви можете це зробити так,

Оновлення для 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
}

Швидкий 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.
    }

Цільовий синтаксис C також дуже схожий.

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

Щоб перевірити наявні на даний момент типи сповіщень, ви можете скористатися методом класу UIApplication,

- (UIUserNotificationSettings *)currentUserNotificationSettings

Отже, якщо користувач сказав "ні" для вашої програми, тоді ця функція повинна повернути налаштування без будь-яких типів.

Я написав підручник з цього приводу, ви могли це побачити тут .


1
Якщо користувач відмовляє у дозволі, як це визначити це пізніше програмно?
jjxtra

@satheeshwaran Коли я використовую цей код, він прекрасно працює з тренажером з iOS8. Я хотів, щоб ціль розгортання мого додатка починалася з iOS7. Тому, коли я запускаю цей код на пристрої iOS7, я отримую цю помилку: dyld: Symbol not found: _OBJC_CLASS_$_UIUserNotificationSettings. Чи є інший спосіб у Swift запитати у користувачів дозволу для роботи в iOS7? будь ласка, допоможіть.
Рагавендра

@Raghav UIUserNotificationSettings доступний лише з iOS 8, і перед вами є правильна поведінка. Не слід використовувати це в iOS 7.
Satheeshwaran

1
-1 для перевірки UIDevice версії iOS. stackoverflow.com/a/25735175/1226304 відповідь має кращий підхід для цього.
дерполюк

3
@derpoliuk Оновлено, як у відповіді на користь усім, гаразд ??
Satheeshwaran

38

Помістіть цей код у контролер перегляду, де ви спочатку запрограмуєте сповіщення (якщо ви запрограмуєте їх при запуску, то це буде application:didFinishLaunchingWithOptions:):

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

У Свіфті:

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

Рішення, які тестують на номер версії системи, є неоптимальними та схильними до помилок.


Я б використав application.respondsToSelector(Selector("registerUserNotificationSettings"))іif ([application respondsToSelector:@selector(registerUserNotificationSettings:)])
дерполюк

7
Ну це лише тому, що ви використовуєте його всередині, application:didFinishLaunchingWithOptions:який забезпечує зручний applicationоб’єкт :)
KPM,

18

Спробуйте це для 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];
  }
}

Для 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

Я просто зіткнувся з тією ж проблемою. Схоже, в iOS 8 нам потрібно зробити додатковий крок, як правило, зроблений всередині:

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

Ви можете використовувати цей код, якщо хочете зберегти його назад сумісним:

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

Система запам'ятає рішення і запитає лише один раз.


Краще перевірити версію iOS за допомогою цього коду, якщо ([[UIDevice currentDevice] .systemVersion floatValue] <10)
Mehul Chuahan

1

** Локальне сповіщення з трьома кнопковими діями для iOS8 +

// Кнопка: Я ТОКУВАТИ ЇЇ, ПОДАЮТЬСЯ пізніше, СКОРОТИТИ **

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

        }

    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.