How to Send Local Notification in SwiftUI?

DevTechie Inc
May 10, 2023

Notifications are used in apps to notify users about an event. Notification contains a message, media type and a sound alert.

Notifications that are initiated by apps running on the device are known as local notifications.

Today we will look into sending scheduled local notifications using SwiftUI.

Let’s start with an example, we will create a view with Text and a Button. Button’s action will be used to schedule and send notification.

struct DevTechieLocalNotification: View {
    var body: some View {
        NavigationStack {
            VStack {
                Text("How to Send Local Notification in SwiftUI?")
                    .bold()
                    .padding()
                    .frame(maxWidth: .infinity)
                    .background(.orange.gradient.opacity(0.5))
                Spacer()
                Button("Schedule Notification") {
                    
                }
                .buttonStyle(.borderedProminent)
                Spacer()
            }
            .navigationTitle("DevTechie")
        }
    }
}

UNUserNotificationCenter manages the notification related tasks and in order to use the notification, we need to get user’s permission by calling requestAuthorization function defined in UNUserNotificationCenter. We will access current instance of notification center and will call the authorization function.

UNUserNotificationCenter.current().requestAuthorization { success, error in}

Another overload of requestAuthorization function takes options as a parameter so we will use that in order to define what kind of notifications we want.

struct DevTechieLocalNotification: View {
    var body: some View {
        NavigationStack {
            VStack {
                Text("How to Send Local Notification in SwiftUI?")
                    .bold()
                    .padding()
                    .frame(maxWidth: .infinity)
                    .background(.orange.gradient.opacity(0.5))
                Spacer()
                Button("Schedule Notification") {
                    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
                        
                    }
                }
                .buttonStyle(.borderedProminent)
                Spacer()
            }
            .navigationTitle("DevTechie")
        }
    }
}

requestAuthorization provides us information of user’s action via trailing closure. We will print success or error states in the console log.

struct DevTechieLocalNotification: View {
    var body: some View {
        NavigationStack {
            VStack {
                Text("How to Send Local Notification in SwiftUI?")
                    .bold()
                    .padding()
                    .frame(maxWidth: .infinity)
                    .background(.orange.gradient.opacity(0.5))
                Spacer()
                Button("Schedule Notification") {
                    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
                        print(success ? "Authorization success" : "Authorization failed")
                        print(error?.localizedDescription ?? "")
                    }
                }
                .buttonStyle(.borderedProminent)
                Spacer()
            }
            .navigationTitle("DevTechie")
        }
    }
}

We can test our code so far by running and pressing the button. We will get to see permission dialog to send notifications.

Next we will build notification content. This is done using UNMutableNotificationContent class instance. We can set title, subtitle, body and sound using UNMutableNotificationContent instance.

struct DevTechieLocalNotification: View {
    var body: some View {
        NavigationStack {
            VStack {
                Text("How to Send Local Notification in SwiftUI?")
                    .bold()
                    .padding()
                    .frame(maxWidth: .infinity)
                    .background(.orange.gradient.opacity(0.5))
                Spacer()
                Button("Schedule Notification") {
                    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
                        print(success ? "Authorization success" : "Authorization failed")
                        print(error?.localizedDescription ?? "")
                    }
                    
                    let content = UNMutableNotificationContent()
                    content.title = "Hey DevTechie!"
                    content.subtitle = "Check out DevTechie.com"
                    content.body = "We have video courses!!!"
                    content.sound = UNNotificationSound.default
                }
                .buttonStyle(.borderedProminent)
                Spacer()
            }
            .navigationTitle("DevTechie")
        }
    }
}

Next we will create and instance of UNTimeIntervalNotificationTrigger .

UNTimeIntervalNotificationTrigger is a trigger condition that causes the system to deliver a notification after the amount of time you specify elapses.

timeInterval is the time (in seconds) that must elapse from the current time before the trigger fires. This value must be greater than zero.

repeats we specify false to deliver the notification one time. We can specify trueto reschedule the notification request each time the system delivers the notification. If this parameter is true, the value in the timeIntervalparameter must be 60 seconds or greater.

We will set trigger’s timeInterval as five seconds and set the repeats to false.

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

We also need an instance of UNNotificationRequest which is a request to schedule a local notification, which includes the content of the notification and the trigger conditions for delivery.

UNNotificationRequest takes three parameters identifier is an identifier for the request; this parameter cannot be nil. We use this identifier to cancel the request if it’s still pending using removePendingNotificationRequests(withIdentifiers:) method.

content is the content of the notification. This parameter cannot be nil.

trigger is the condition that causes the system to deliver the notification. We specify nil to deliver the notification right away.

let request = UNNotificationRequest(identifier: "com.devtechie.notification", content: content, trigger: trigger)

Lastly we add this notification to the notification center:

UNUserNotificationCenter.current().add(request)

Our complete code will look like this:

struct DevTechieLocalNotification: View {
    var body: some View {
        NavigationStack {
            VStack {
                Text("How to Send Local Notification in SwiftUI?")
                    .bold()
                    .padding()
                    .frame(maxWidth: .infinity)
                    .background(.orange.gradient.opacity(0.5))
                Spacer()
                Button("Schedule Notification") {
                    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
                        print(success ? "Authorization success" : "Authorization failed")
                        print(error?.localizedDescription ?? "")
                    }
                    
                    let content = UNMutableNotificationContent()
                    content.title = "Hey DevTechie!"
                    content.subtitle = "Check out DevTechie.com"
                    content.body = "We have video courses!!!"
                    content.sound = UNNotificationSound.default
                    
                    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5 , repeats: false)
                    let request = UNNotificationRequest(identifier: "com.devtechie.notification", content: content, trigger: trigger)
                    
                    UNUserNotificationCenter.current().add(request)
                    
                }
                .buttonStyle(.borderedProminent)
                Spacer()
            }
            .navigationTitle("DevTechie")
        }
    }
}

Build and run

Sending Attachments with Notification

We can even send visual and audio attachments to display alongside the notification’s main content.

We will grab an image located in our bundle and add that as an attachment to the notification.

struct DevTechieLocalNotification: View {
    var body: some View {
        NavigationStack {
            VStack {
                Text("How to Send Local Notification in SwiftUI?")
                    .bold()
                    .padding()
                    .frame(maxWidth: .infinity)
                    .background(.orange.gradient.opacity(0.5))
                Spacer()
                Button("Schedule Notification") {
                    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
                        print(success ? "Authorization success" : "Authorization failed")
                        print(error?.localizedDescription ?? "")
                    }
                    
                    let content = UNMutableNotificationContent()
                    content.title = "Hey DevTechie!"
                    content.subtitle = "Check out DevTechie.com"
                    content.body = "We have video courses!!!"
                    content.sound = UNNotificationSound.default
                    let imageName = "DT"
                    if let imageURL = Bundle.main.url(forResource: imageName, withExtension: "png") {
                        let attachment = try! UNNotificationAttachment(identifier: imageName, url: imageURL, options: .none)
                        
                        content.attachments = [attachment]
                    }
                    
                    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5 , repeats: false)
                    let request = UNNotificationRequest(identifier: "com.devtechie.notification", content: content, trigger: trigger)
                    
                    UNUserNotificationCenter.current().add(request)
                    
                }
                .buttonStyle(.borderedProminent)
                Spacer()
            }
            .navigationTitle("DevTechie")
        }
    }
}

Build and run one more time: