要求用户权限在iOS 8中接收UILocalNotifications

dan*_*ler 115 notifications cocoa-touch ios uilocalnotification ios8

我在App Delegate中设置了本地通知使用此方法:

- (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]];
}
Run Code Online (Sandbox Code Playgroud)

当我运行应用程序然后退出它时,我收到一条错误消息:

2014-06-07 11:14:16.663 CCA-TV [735:149070] 试图安排本地通知 {开火日期= 2014年6月7日星期六太平洋夏令时间11:14:21,时区= America/Los_Angeles (PDT)偏移-25200(日光),重复间隔= 0,重复计数= UILocalNotificationInfiniteRepeatCount,下一个开火日期= 2014年6月7日星期六太平洋夏令时间11:14:21,用户信息=(null)} 带警报但尚未收到用户显示警报的许可

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

Sat*_*ran 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
}
Run Code Online (Sandbox Code Playgroud)

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.
    }
Run Code Online (Sandbox Code Playgroud)

Objective 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;
}
Run Code Online (Sandbox Code Playgroud)

要检查当前注册的通知类型,可以使用UIApplication类的方法,

- (UIUserNotificationSettings *)currentUserNotificationSettings
Run Code Online (Sandbox Code Playgroud)

因此,如果用户对您的应用程序说"不",则此函数应返回其中没有任何类型的设置.

我已经写了一个关于这个的教程,你可以在这里看到它.

  • @derpoliuk在答案中更新了每个人的好处,好吗? (3认同)

KPM*_*KPM 38

将此代码放在视图控制器中,您将首先对通知进行编程(如果您在启动时对它们进行编程,那么它将是application:didFinishLaunchingWithOptions:):

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

在Swift中:

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

针对系统版本号进行测试的解决方案是次优的且容易出错.

  • 那只是因为你在`application:didFinishLaunchingWithOptions:`中使用它,它提供了一个方便的`application`对象:) (7认同)

Nag*_*jun 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];
  }
}
Run Code Online (Sandbox Code Playgroud)

对于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
}
Run Code Online (Sandbox Code Playgroud)


ppa*_*ica 5

我刚遇到同样的问题.似乎在iOS 8中我们需要做一个额外的步骤,通常在内部完成:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { /*...*/ }
Run Code Online (Sandbox Code Playgroud)

如果要保持向后兼容,可以使用此代码:

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

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