How to create local notifications?
How can I setup local notifications so that at the time I set, my app generates a notification/alert with a customized message?
Solution 1:
Here is sample code for LocalNotification that worked for my project.
Objective-C:
This code block in AppDelegate
file :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[launchOptions valueForKey:UIApplicationLaunchOptionsLocalNotificationKey];
// Override point for customization after application launch.
return YES;
}
// This code block is invoked when application is in foreground (active-mode)
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
UIAlertView *notificationAlert = [[UIAlertView alloc] initWithTitle:@"Notification" message:@"This local notification"
delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
[notificationAlert show];
// NSLog(@"didReceiveLocalNotification");
}
This code block in .m file of any ViewController
:
-(IBAction)startLocalNotification { // Bind this method to UIButton action
NSLog(@"startLocalNotification");
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:7];
notification.alertBody = @"This is local notification!";
notification.timeZone = [NSTimeZone defaultTimeZone];
notification.soundName = UILocalNotificationDefaultSoundName;
notification.applicationIconBadgeNumber = 10;
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
The above code display an AlertView after time interval of 7 seconds when pressed on button that binds startLocalNotification
If application is in background then it displays BadgeNumber
as 10 and with default notification sound.
This code works fine for iOS 7.x and below but for iOS 8 it will prompt following error on console:
Attempting to schedule a local notification with an alert but haven't received permission from the user to display alerts
This means you need register for local notification. This can be achieved using:
if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]){
[application registerUserNotificationSettings [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}
You can also refer blog for local notification.
Swift:
You AppDelegate.swift
file should look like this:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: UIUserNotificationType.Sound | UIUserNotificationType.Badge | UIUserNotificationType.Alert, categories: nil))
return true
}
The swift file (say ViewController.swift
) in which you want to create local notification should contain below code:
//MARK: - Button functions
func buttonIsPressed(sender: UIButton) {
println("buttonIsPressed function called \(UIButton.description())")
var localNotification = UILocalNotification()
localNotification.fireDate = NSDate(timeIntervalSinceNow: 3)
localNotification.alertBody = "This is local notification from Swift 2.0"
localNotification.timeZone = NSTimeZone.localTimeZone()
localNotification.repeatInterval = NSCalendarUnit.CalendarUnitMinute
localNotification.userInfo = ["Important":"Data"];
localNotification.soundName = UILocalNotificationDefaultSoundName
localNotification.applicationIconBadgeNumber = 5
localNotification.category = "Message"
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
}
//MARK: - viewDidLoad
class ViewController: UIViewController {
var objButton : UIButton!
. . .
override func viewDidLoad() {
super.viewDidLoad()
. . .
objButton = UIButton.buttonWithType(.Custom) as? UIButton
objButton.frame = CGRectMake(30, 100, 150, 40)
objButton.setTitle("Click Me", forState: .Normal)
objButton.setTitle("Button pressed", forState: .Highlighted)
objButton.addTarget(self, action: "buttonIsPressed:", forControlEvents: .TouchDown)
. . .
}
. . .
}
The way you use to work with Local Notification in iOS 9 and below is completely different in iOS 10.
Below screen grab from Apple release notes depicts this.
You can refer apple reference document for UserNotification.
Below is code for local notification:
Objective-C:
In
App-delegate.h
file use@import UserNotifications;
App-delegate should conform to
UNUserNotificationCenterDelegate
protocol-
In
didFinishLaunchingOptions
use below code:UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) { if (!error) { NSLog(@"request authorization succeeded!"); [self showAlert]; } }]; -(void)showAlert { UIAlertController *objAlertController = [UIAlertController alertControllerWithTitle:@"Alert" message:@"show an alert!" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { NSLog(@"Ok clicked!"); }]; [objAlertController addAction:cancelAction]; [[[[[UIApplication sharedApplication] windows] objectAtIndex:0] rootViewController] presentViewController:objAlertController animated:YES completion:^{ }]; }
-
Now create a button in any view controller and in IBAction use below code :
UNMutableNotificationContent *objNotificationContent = [[UNMutableNotificationContent alloc] init]; objNotificationContent.title = [NSString localizedUserNotificationStringForKey:@“Notification!” arguments:nil]; objNotificationContent.body = [NSString localizedUserNotificationStringForKey:@“This is local notification message!“arguments:nil]; objNotificationContent.sound = [UNNotificationSound defaultSound]; // 4. update application icon badge number objNotificationContent.badge = @([[UIApplication sharedApplication] applicationIconBadgeNumber] + 1); // Deliver the notification in five seconds. UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:10.f repeats:NO]; UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@“ten” content:objNotificationContent trigger:trigger]; // 3. schedule localNotification UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { if (!error) { NSLog(@“Local Notification succeeded“); } else { NSLog(@“Local Notification failed“); } }];
Swift 3:
- In
AppDelegate.swift
file useimport UserNotifications
- Appdelegate should conform to
UNUserNotificationCenterDelegate
protocol -
In
didFinishLaunchingWithOptions
use below code// Override point for customization after application launch. let center = UNUserNotificationCenter.current() center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in // Enable or disable features based on authorization. if error != nil { print("Request authorization failed!") } else { print("Request authorization succeeded!") self.showAlert() } } func showAlert() { let objAlert = UIAlertController(title: "Alert", message: "Request authorization succeeded", preferredStyle: UIAlertControllerStyle.alert) objAlert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)) //self.presentViewController(objAlert, animated: true, completion: nil) UIApplication.shared().keyWindow?.rootViewController?.present(objAlert, animated: true, completion: nil) }
-
Now create a button in any view controller and in IBAction use below code :
let content = UNMutableNotificationContent() content.title = NSString.localizedUserNotificationString(forKey: "Hello!", arguments: nil) content.body = NSString.localizedUserNotificationString(forKey: "Hello_message_body", arguments: nil) content.sound = UNNotificationSound.default() content.categoryIdentifier = "notify-test" let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 5, repeats: false) let request = UNNotificationRequest.init(identifier: "notify-test", content: content, trigger: trigger) let center = UNUserNotificationCenter.current() center.add(request)
Solution 2:
In appdelegate.m file write the follwing code in applicationDidEnterBackground to get the local notification
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UILocalNotification *notification = [[UILocalNotification alloc]init];
notification.repeatInterval = NSDayCalendarUnit;
[notification setAlertBody:@"Hello world"];
[notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:1]];
[notification setTimeZone:[NSTimeZone defaultTimeZone]];
[application setScheduledLocalNotifications:[NSArray arrayWithObject:notification]];
}
Solution 3:
Creating local notifications are pretty easy. Just follow these steps.
-
On viewDidLoad() function ask user for permission that your apps want to display notifications. For this we can use the following code.
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge], completionHandler: {didAllow, error in })
-
Then you can create a button, and then in the action function you can write the following code to display a notification.
//creating the notification content let content = UNMutableNotificationContent() //adding title, subtitle, body and badge content.title = "Hey this is Simplified iOS" content.subtitle = "iOS Development is fun" content.body = "We are learning about iOS Local Notification" content.badge = 1 //getting the notification trigger //it will be called after 5 seconds let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) //getting the notification request let request = UNNotificationRequest(identifier: "SimplifiedIOSNotification", content: content, trigger: trigger) //adding the notification to notification center UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
Notification will be displayed, just click on home button after tapping the notification button. As when the application is in foreground the notification is not displayed. But if you are using iPhone X. You can display notification even when the app is in foreground. For this you just need to add a delegate called UNUserNotificationCenterDelegate
For more details visit this blog post: iOS Local Notification Tutorial
Solution 4:
Updated with Swift 5 Generally we use three type of Local Notifications
- Simple Local Notification
- Local Notification with Action
- Local Notification with Content
Where you can send simple text notification or with action button and attachment.
Using UserNotifications package in your app, the following example Request for notification permission, prepare and send notification as per user action AppDelegate itself, and use view controller listing different type of local notification test.
AppDelegate
import UIKit
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
let notificationCenter = UNUserNotificationCenter.current()
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//Confirm Delegete and request for permission
notificationCenter.delegate = self
let options: UNAuthorizationOptions = [.alert, .sound, .badge]
notificationCenter.requestAuthorization(options: options) {
(didAllow, error) in
if !didAllow {
print("User has declined notifications")
}
}
return true
}
func applicationWillResignActive(_ application: UIApplication) {
}
func applicationDidEnterBackground(_ application: UIApplication) {
}
func applicationWillEnterForeground(_ application: UIApplication) {
}
func applicationWillTerminate(_ application: UIApplication) {
}
func applicationDidBecomeActive(_ application: UIApplication) {
UIApplication.shared.applicationIconBadgeNumber = 0
}
//MARK: Local Notification Methods Starts here
//Prepare New Notificaion with deatils and trigger
func scheduleNotification(notificationType: String) {
//Compose New Notificaion
let content = UNMutableNotificationContent()
let categoryIdentifire = "Delete Notification Type"
content.sound = UNNotificationSound.default
content.body = "This is example how to send " + notificationType
content.badge = 1
content.categoryIdentifier = categoryIdentifire
//Add attachment for Notification with more content
if (notificationType == "Local Notification with Content")
{
let imageName = "Apple"
guard let imageURL = Bundle.main.url(forResource: imageName, withExtension: "png") else { return }
let attachment = try! UNNotificationAttachment(identifier: imageName, url: imageURL, options: .none)
content.attachments = [attachment]
}
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
let identifier = "Local Notification"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
notificationCenter.add(request) { (error) in
if let error = error {
print("Error \(error.localizedDescription)")
}
}
//Add Action button the Notification
if (notificationType == "Local Notification with Action")
{
let snoozeAction = UNNotificationAction(identifier: "Snooze", title: "Snooze", options: [])
let deleteAction = UNNotificationAction(identifier: "DeleteAction", title: "Delete", options: [.destructive])
let category = UNNotificationCategory(identifier: categoryIdentifire,
actions: [snoozeAction, deleteAction],
intentIdentifiers: [],
options: [])
notificationCenter.setNotificationCategories([category])
}
}
//Handle Notification Center Delegate methods
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
if response.notification.request.identifier == "Local Notification" {
print("Handling notifications with the Local Notification Identifier")
}
completionHandler()
}
}
and ViewController
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var appDelegate = UIApplication.shared.delegate as? AppDelegate
let notifications = ["Simple Local Notification",
"Local Notification with Action",
"Local Notification with Content",]
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - Table view data source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return notifications.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = notifications[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let notificationType = notifications[indexPath.row]
let alert = UIAlertController(title: "",
message: "After 5 seconds " + notificationType + " will appear",
preferredStyle: .alert)
let okAction = UIAlertAction(title: "Okay, I will wait", style: .default) { (action) in
self.appDelegate?.scheduleNotification(notificationType: notificationType)
}
alert.addAction(okAction)
present(alert, animated: true, completion: nil)
}
}