How to Make Local Notifications in iOS 10

I’ve written before about local notifications in iOS. However, Apple has changed all that starting in iOS 10. In versions earlier than iOS 10, notifications were part of UIKit, but required the developer to make changes to the view controller and app delegate. Different types of notifications had different code. In iOS 10 notifications unifies the coding of notifications into the view controller.

There are two types of notifications: Local and remote notifications. Remote notification require connection to a server which pushes the notification to your device. These are beyond the scope of this lesson. Local notifications are notifications for events that happen on your device. We’ll set up these types of notifications in this lesson

Make A New Project

Make new single-view project named LocalNotificationDemo with Swift as the language. Go to the storyboard. Add a button centered on the view labeled 10 Second Notification. Using the align button alignment iconin auto layout, center the button like this.

2016-08-08_05-42-13

Be sure to check the update frame Items to New Constraints. You’ll have a storyboard like this:

2016-08-08_05-46-41

Open the assistant editor and make an action send10SecNotification to the button by control-dragging to the view controller code. Close the assistant editor.

Add the Framework

Notifications are a new framework. Go the to the viewcontroller.swift code and add the following under import UIKit :

import UserNotifications

This added the framework for the user notifications.

Check for Permission

Before any notification, we’ll need to check if the user allows us to use notifications. We only do this once, so add this to viewDidLoad:

override func viewDidLoad()
     super.viewDidLoad()
     UNUserNotificationCenter.current().requestAuthorization(
         options: [.alert,.sound,.badge],
         completionHandler: { (granted,error) in
             self.isGrantedNotificationAccess = granted
         }
    )
}

The object UNUserNotificationCenter.current() returns the current notification center. We ask for authorization with the requestAuthorization(options:completionHander) method. We have three options we can use to give an alert:

  • .alert – Display the alert window and text of the notification
  • .sound – Plays a sound or vibrates. On Apple Watch uses a haptic.
  • .badge – Places the red dot of the app to give a count of notifications from the app.

The argument options is an array. We add which of these three we wish to use for our notification.

The completion handler has two arguments grants and error. You can use these to handle the user preferences in notifications. Here I’ve set a Bool value I’ll use in the action. Add the property to the viewController class

var isGrantedNotificationAccess:Bool = false

Add this to the send10SecNotification action:

@IBAction func send10SecNotification(_ sender: UIButton) {
    if isGrantedNotificationAccess{
        //add notification code here
    }
}

This prevents the notification from scheduling if the user doesn’t want one.

Setting up Content

The notification is put together a lot like an onion – it has layers on top of layers. One layer creates the content of the notification . Add this under the //add notification code here comment:

let content = UNMutableNotificationContent()
content.title = "10 Second Notification Demo"
content.subtitle = "From MakeAppPie.com"
content.body = "Notification after 10 seconds - Your pizza is Ready!!"
content.categoryIdentifier = "message"

The UNMutableNotificationContent object contains all the content in a notification. We’ve included all the text properties title, subtitle and body, but you can add media content as well. An important property is the categoryIdentifier, which will help us in a few steps associate actions to the notification.

Setting Up Triggers

Triggers are the events which set off a notification. In earlier versions of iOS, there was only one easily accessible trigger: time expressed as a date. For local notifications, you have triggers for times, dates, and locations. There’s one more type of trigger for a remote notification. We’ll use the time interval trigger to set a trigger for ten seconds.

let trigger = UNTimeIntervalNotificationTrigger(
    timeInterval: 10.0,
    repeats: false)

For the time interval trigger, we have another new argument: repeats. If you need multiples of the same notification,set this to true. This is a feature added to iOS 10. In earlier versions of notifications, multiple notifications needed to be scheduled clogging up you limited number of notifications. If repeats is true, then there is only one. The notification triggers, deletes itself from the schedule then re-assigns itself.

Adding the Notification Request

We’ll take the trigger and content, add a string to name the request and whip them together in a UNNotificationRequest like this:


let request = UNNotificationRequest(
    identifier: "10.second.message",
    content: content,
    trigger: trigger
)

The identifier plays an important role. The system will prevent conflicts of the same notifications firing simultaneously. The watch and the phone may want to display the same local notification, but the system will see the identifier, and choose only one. The identifier also gives the developer control of the notifications. To stop a repeating UNTimeIntervalNotificationTrigger, there is a method to delete the notification you’d have to implement.

Adding the Notification

Once you have a request, add it to the current notification center

UNUserNotificationCenter.current().add(
    request, withCompletionHandler: nil)

Build and Run. On the first execution, we’ll be asked for permission to use notifications. After this first answer, the device will store the answer in the settings for the app.

2016-08-08_06-28-13

The user can change it at any time in the user settings, though the change will not take until the next start of the application.

Allow notifications. When the application appears, Press the button and then press Command-Shift-H to go to the home screen. Wait ten seconds. You will see this:

2016-08-08_06-29-00

Click on the notification, and you are back in the app. Click the button again, and press Command-L to simulate the user locking their phone. After ten seconds you get this:

2016-08-08_06-31-46

Click on the notification then open the phone with Command-Shift-H for the home button. You are back in the app.

That’s how to make a basic notification in iOS. You can use the same code in WatchOS to get local notifications as well. There’s a lot more to explore in notifications, but that will be in another lesson.

The Whole Code

//
//  ViewController.swift
//  LocalNotificationDemo
//  A Very Basic Local Notification
//  Created by Steven Lipton on 8/8/16.
//  Copyright © 2016 Steven Lipton. All rights reserved.
//

import UIKit
import UserNotifications

class ViewController: UIViewController, UNUserNotificationCenterDelegate {
    var isGrantedNotificationAccess:Bool = false
    @IBAction func send10SecNotification(_ sender: UIButton) {
        if isGrantedNotificationAccess{
            //add notification code here
            
            //Set the content of the notification
            let content = UNMutableNotificationContent()
            content.title = "10 Second Notification Demo"
            content.subtitle = "From MakeAppPie.com"
            content.body = "Notification after 10 seconds - Your pizza is Ready!!"
            
            //Set the trigger of the notification -- here a timer. 
            let trigger = UNTimeIntervalNotificationTrigger(
                timeInterval: 10.0,
                repeats: false)
            
            //Set the request for the notification from the above
            let request = UNNotificationRequest(
                identifier: "10.second.message",
                content: content,
                trigger: trigger
            )
            
            //Add the notification to the currnet notification center
            UNUserNotificationCenter.current().add(
                request, withCompletionHandler: nil)
            
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        UNUserNotificationCenter.current().requestAuthorization(
            options: [.alert,.sound,.badge],
            completionHandler: { (granted,error) in
                self.isGrantedNotificationAccess = granted
            }
        )
    }



}

19 Replies to “How to Make Local Notifications in iOS 10”

  1. Great article!
    I would include the following instead:
    UNUserNotificationCenter.current().add(request) { (error) in
    UNUserNotificationCenter.current().delegate = self
    print(error)
    }

    Cheers ;)

  2. Great Article! I tried to adapt the steps for a Apple Watch only local notification (Button on Watch, Permission on Watch, …) but couldn’t get a repeating notification. Any suggestion or sample would be appreciated!

  3. I’m switching my App to swift 3.0 and also want to adopt the new UserNotifications, so far it works fine, but for now a previous (iOS9) scheduled Notification that shows every day is still popping up (I can tell because the new ones look a little different)
    So i thought i check if any old Notifications are scheduled and just cancel them, but it turn out the new System is scheduling them in the same place so this code:

    if (UIApplication.shared.scheduledLocalNotifications?.count)! > 0 {
    print(“Scheduled Notifications: \(UIApplication.shared.scheduledLocalNotifications)”)
    UIApplication.shared.cancelAllLocalNotifications()
    print(“Scheduled Notifications: \(UIApplication.shared.scheduledLocalNotifications)”)

    UNUserNotificationCenter.current().requestAuthorization(
    options: [.alert, .sound]) {(granted, error) in
    if granted {
    print(“Notification access granted.”)
    DispatchQueue.main.async { () -> Void in
    let start = self.userDefaults?.value(forKey: “dailyStart”)
    NewNotificationManager.sharedManager.scheduleDailyNotification(withDate: start as! Date)
    NewNotificationManager.sharedManager.scheduleNotification(withTime: 3600)
    print(“Scheduled Notifications: \(UIApplication.shared.scheduledLocalNotifications)”)
    }
    } else {
    print(“Notification access denied.”)
    DispatchQueue.main.async { () -> Void in
    }
    }
    }
    }
    works but will be run every time because the new system writes into the same scheduledLocalNotifications.
    Any idea i can handle this?

    1. I was actually going to write this all up in two weeks but it look like this week. So the full answer will be Monday. I have no code written, but Instead of looking in UIApplication I’d look in the current UNNotificationCenter. There is a few methods there including removeAllPendingNotifications, which might kill off or suppress that pesky notification. There are methods there using closures which can list the pending notifications too, and you might be able to get its ID and kill it there too.

      Here’s the reference for the Apple documentation

      https://developer.apple.com/reference/usernotifications/unusernotificationcenter

      Hope that helps

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s