要求用户许可以在iOS 8中接收UILocalNotifications


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] 尝试安排本地通知 {触发日期= 2014年6月7日,星期六,太平洋夏令时,时区= America / Los_Angeles (PDT)偏移量-25200(日光),重复间隔= 0,重复计数= UILocalNotificationInfiniteRepeatCount,下次触发日期= 2014年6月7日,星期六,太平洋夏令时间,用户信息=(空)},并带有警报但尚未获得用户显示警报的权限

如何获得显示警报的必要权限?


1
我认为该应用一次拒绝了该权限,您可以尝试通过“设置”启用该功能。不过顺便说UILocalNotification不需要用户权限..
iphonic

尝试registerUserNotificationSettings。如果是iOS 8,该线程将回答您的问题。但是,G提前看看- stackoverflow.com/questions/24006998/...
raurora

Answers:


237

由于iOS 8,您需要征求用户的许可才能显示来自您应用的通知,这适用于远程/推送通知和本地通知。在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 2014年

@satheeshwaran当我使用此代码时,它与iOS8的模拟器配合良好。我希望我的应用程序的部署目标从iOS7开始。因此,当我在iOS7设备上运行此代码时,出现以下错误:dyld: Symbol not found: _OBJC_CLASS_$_UIUserNotificationSettings。Swift中还有其他方法可以向用户询问权限以便在iOS7中工作吗?请帮忙。
Raghavendra 2014年

@Raghav UIUserNotificationSettings仅在iOS 8中可用,并且您所面对的是正确的行为。在iOS的7。你不应该使用这个
Satheeshwaran

1
-1用于检查iOS版本的UIDevice。stackoverflow.com/a/25735175/1226304答案具有更好的方法来执行此操作。
derpoliuk 2014年

3
@derpoliuk为所有人的利益更新为答案,好吗?
Satheeshwaran 2014年

38

将此代码放在视图控制器中,您将在其中首先编写通知(如果在启动时编写通知,那么它将为application:didFinishLaunchingWithOptions:):

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

在Swift中:

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

针对系统版本号进行测试的解决方案不是最优的,而且容易出错。


我会用application.respondsToSelector(Selector("registerUserNotificationSettings"))if ([application respondsToSelector:@selector(registerUserNotificationSettings:)])
derpoliuk

7
好吧,这仅仅是因为您在内部使用它application:didFinishLaunchingWithOptions:提供了一个方便的application对象:)
KPM 2014年

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

系统将记住该决定,并且只会询问一次。


如果([[[UIDevice currentDevice] .systemVersion floatValue] <10),则最好使用此代码检查iOS版本
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()

        }

    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.