[英]Ask for Permission for Local Notifications in iOS 8, but still have the App Support iOS 7
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.
在iOS 7中,一切正常,但在iOS 8中,应用程序需要请求用户显示通知的权限。 To ask for permission in iOS 8 I'm using:
要在iOS 8中请求权限我正在使用:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}
It works fine in Xcode 6 and in iOS 8. When I open the same project in Xcode 5, the error is a Semantic Issue. 它在Xcode 6和iOS 8中工作正常。当我在Xcode 5中打开相同的项目时,错误是语义问题。 "Use of undeclared identifier 'UIUserNotificationSettings'."
“使用未声明的标识符'UIUserNotificationSettings'。”
How can I get the app to work with iOS 7 & 8, and have the notifications work properly on both versions. 如何让应用程序与iOS 7和8一起使用,并使这两个版本的通知正常工作。
The following answer makes a few assumptions: 以下答案做了一些假设:
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 . 所有这些都包含在Apple SDK兼容性指南中 。
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];
}
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: 如果您仍想针对较旧的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
}
This should perfectly compile on iOS 7 SDK and work (effectively) on iOS 8 devices, ignored on older ones. 这应该在iOS 7 SDK上完美编译并在iOS 8设备上有效工作,在旧版设备上忽略。
Migrating your project to iOS 8 SDK is another solution, thought, but there are still options. 想到,将项目迁移到iOS 8 SDK是另一种解决方案,但仍有一些选择。
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)];
}
if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil];
[application registerUserNotificationSettings:settings];
}
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 **编辑**固定代码更好
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.