繁体   English   中英

在iOS 8中要求获得本地通知的权限,但仍然拥有iOS 7应用程序支持

[英]Ask for Permission for Local Notifications in iOS 8, but still have the App Support iOS 7

我有一个使用本地通知的应用程序。 在iOS 7中,一切正常,但在iOS 8中,应用程序需要请求用户显示通知的权限。 要在iOS 8中请求权限我正在使用:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{
  [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}

它在Xcode 6和iOS 8中工作正常。当我在Xcode 5中打开相同的项目时,错误是语义问题。 “使用未声明的标识符'UIUserNotificationSettings'。”

如何让应用程序与iOS 7和8一起使用,并使这两个版本的通知正常工作。

以下答案做了一些假设:

  1. 使用Xcode 6时,应用必须使用iOS 8的Base SDK正确构建,并且在使用Xcode 5时必须使用iOS 7的Base SDK正确构建。
  2. 无论Base SDK和Xcode版本如何,该应用程序都必须支持iOS 7(或更早版本)的部署目标。

码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // None of the code should even be compiled unless the Base SDK is iOS 8.0 or later
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
    // The following line must only run under iOS 8. This runtime check prevents
    // it from running if it doesn't exist (such as running under iOS 7 or earlier).
    if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
        [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
    }
#endif
}

所有这些都包含在Apple SDK兼容性指南中

我简单地实施了 -

if([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {

    [[UIApplication sharedApplication] registerForRemoteNotifications];
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];

} else {
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge];
}

如果您仍想针对较旧的SDK进行编译或有特殊原因这样做,您可以尝试动态调用整个内容:

#ifdef __IPHONE_8_0
#define USING_IOS8_SDK
#else // iOS <8 SDK compatibility definitions
#define UIUserNotificationTypeNone    (0)
#define UIUserNotificationTypeBadge   (1 << 0)
#define UIUserNotificationTypeSound   (1 << 1)
#define UIUserNotificationTypeAlert   (1 << 2)
#endif


...

if ([_sharedApplication respondsToSelector:NSSelectorFromString(@"registerUserNotificationSettings:")])
{
    NSUInteger settingsParam = (UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound);
    id categoriesParam = nil;

#ifdef USING_IOS8_SDK

    // Perform direct call when using iOS 8 SDK
    [_sharedApplication registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:settingsParam categories:categoriesParam]];

#else
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

    // Do the dynamic stuff

    // Get UIUserNotificationSettings class reference
    Class settings = NSClassFromString(@"UIUserNotificationSettings");
    if (settings) {

        // Prepare class selector
        SEL sel = NSSelectorFromString(@"settingsForTypes:categories:");

        // Obtain a method signature of selector on UIUserNotificationSettings class
        NSMethodSignature *signature = [settings methodSignatureForSelector:sel];

        // Create an invocation on a signature -- must be used because of primitive (enum) arguments on selector
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
        invocation.selector = sel;
        invocation.target = settings;

        // Set arguments
        [invocation setArgument:&settingsParam atIndex:2];
        [invocation setArgument:&categoriesParam atIndex:3];

        // Obtain an instance by firing an invocation
        NSObject *settingsInstance;
        [invocation invoke];
        [invocation getReturnValue:&settingsInstance];

        // Retain an instance so it can live after quitting method and prevent crash :-)
        CFRetain((__bridge CFTypeRef)(settingsInstance));

        // Finally call the desired method with proper settings
        if (settingsInstance)
            [_sharedApplication performSelector:NSSelectorFromString(@"registerUserNotificationSettings:") withObject:settingsInstance];
    }

#pragma clang diagnostic pop
#endif
}

这应该在iOS 7 SDK上完美编译并在iOS 8设备上有效工作,在旧版设备上忽略。

想到,将项目迁移到iOS 8 SDK是另一种解决方案,但仍有一些选择。

到目前为止,这段代码片段对我有用,并且易于重用:

//-- Set Notification
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
    [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
    [[UIApplication sharedApplication] registerForRemoteNotifications];
}
else
{
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
     (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
}
if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil];
    [application registerUserNotificationSettings:settings];
}

你可以尝试这样的事情:

if (NSClassFromString(@"UIUserNotificationSettings") != nil) {
    // your iOS 8 code here
    #define isiOS8
}
else {
    #undef isiOS8
}

#ifdef isiOS8
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
#endif

它有点复杂,但它工作正常。

**编辑**固定代码更好

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM