I have set up local notifications in the App Delegate Using this:
- (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]];
}
When I run the app and then quit it I receive an error saying:
2014-06-07 11:14:16.663 CCA-TV[735:149070] Attempting to schedule a local notification {fire date = Saturday, June 7, 2014 at 11:14:21 Pacific Daylight Time, time zone = America/Los_Angeles (PDT) offset -25200 (Daylight), repeat interval = 0, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Saturday, June 7, 2014 at 11:14:21 Pacific Daylight Time, user info = (null)} with an alert but haven't received permission from the user to display alerts
How can I get the necessary permission to display the alerts?
Since iOS 8 you need to ask user's permission to show notifications from your app, this applies for both remote/push and local notifications. In Swift you can do it like this,
Update for 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
}
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.
}
Objective C syntax is also very similar.
- (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;
}
To check for currently registered notification types you can use UIApplication class's method,
- (UIUserNotificationSettings *)currentUserNotificationSettings
So if the user has said no to your app then this function should return a setting without any types in it.
I have written a tutorial about this, you could see it here.
Put this code in the view controller where you will first program the notifications (if you program them at launch, then it will be application:didFinishLaunchingWithOptions:):
if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeSound categories:nil]];
}
In Swift:
if(UIApplication.instancesRespondToSelector(Selector("registerUserNotificationSettings:"))) {
UIApplication.sharedApplication().registerUserNotificationSettings(UIUserNotificationSettings(forTypes: .Alert | .Sound, categories: nil))
}
The solutions that test against system version number are sub-optimal and error-prone.
Try this for 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];
}
}
For 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
}
I just faced the same problem. Seems like in iOS 8 we need to do an additional step, usually done inside:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { /*...*/ }
You can use this code if you want to keep it backward compatible:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)])
{
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]];
}
#endif
The system will remember the decision, and will only ask once.
**Local Notification with three button action for iOS8+
//Button : I TOOK IT , REMIND LATER , SKIP IT**
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()
}
}
来源:https://stackoverflow.com/questions/24100313/ask-for-user-permission-to-receive-uilocalnotifications-in-ios-8