They let users know that your app has relevant information for them to view. Because the user might consider notification-based interactions disruptive, you must obtain permission to use them.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With