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

后端 未结 6 1935

I have an app which uses local notifications. In iOS 7 everything works fine, but in iOS 8 the app needs to ask for user permission to display notifications. To ask for perm

相关标签:
6条回答
  • 2020-12-13 09:49

    You can try something like this:

    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
    

    It's a bit more convoluted but it works fine.

    ** EDIT ** Fixed code better

    0 讨论(0)
  • 2020-12-13 09:50

    The following answer makes a few assumptions:

    1. The app must build properly with a Base SDK of iOS 8 when using Xcode 6 and it must build properly with a Base SDK of iOS 7 when using Xcode 5.
    2. The app must support a Deployment Target of iOS 7 (or earlier) regardless of the Base SDK and Xcode version.

    Code:

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

    All of this is covered in the Apple SDK Compatibility Guide.

    0 讨论(0)
  • 2020-12-13 09:50

    I have implemented simply -

    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];
    }
    
    0 讨论(0)
  • 2020-12-13 09:52

    So far, this code snippet works for me, and its simple to reuse:

    //-- 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)];
    }
    
    0 讨论(0)
  • 2020-12-13 10:03
    if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil];
        [application registerUserNotificationSettings:settings];
    }
    
    0 讨论(0)
  • 2020-12-13 10:06

    In case you still want to compile against older SDKs or have a special reason to do so, you may try calling the whole stuff dynamically:

    #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
    }
    

    This should perfectly compile on iOS 7 SDK and work (effectively) on iOS 8 devices, ignored on older ones.

    Migrating your project to iOS 8 SDK is another solution, thought, but there are still options.

    0 讨论(0)
提交回复
热议问题