iosswiftusernotifications

iOS User Notifications: Prerequisites for a scheduled notification to appear?


For getting familiar with iOS User Notification I made a trial-app.

Here's the source-code:

import SwiftUI
import UserNotifications

struct ContentView: View {
    var body: some View {
        VStack(spacing: 30) {
            Button("Schedule User Notification") {
                Task {
                    let center = UNUserNotificationCenter.current()
                    
                    do {
                        let answer = try await center.requestAuthorization(options: [.alert, .badge])
                        switch answer {
                            case true:
                                scheduleNotification()
                                print("Called: scheduleNotification")
                            case false:
                                print("Permission Denied")
                                try await center.requestAuthorization(options: [.alert, .badge])
                        }
                    } catch {
                        print(error)
                    }
                }
            }.buttonStyle(.borderedProminent)
        }
        .padding()
    }
    
    func scheduleNotification() {
        let content = UNMutableNotificationContent()
        content.title = "Title [\(Date.now.formatted(date: .abbreviated, time: .shortened))]"
        content.subtitle = "Notification-Subtitle"
        content.body = "Notification-Body"
        
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 10, repeats: false)
        let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        
        UNUserNotificationCenter.current().add(request)
        { error in
            if let error = error {
                print(error.localizedDescription)
            } else {
                print("Notification scheduled")
            }
        }
    }
}

Generally, the shown code works.

But it isn't clear to me, in which state the device has to be, that the notification appears.

When the app is in the foreground, the notification doesn't appear. I have got it appearing, when I press the schedule-notification button, then lock the screen, wait for 10 seconds, then press home-button of the emulator.

What are the prerequisite for user-notifications to appear?

Becomes a scheduled notification discarded, when the timerInterval runs out and the app is in the foreground? Is it then gone or does it become kept somehow, for appearing later?


Solution

    1. UserNotification should be in the background mode to appear
    2. To avoid losing any notifications in foreground mode, you can subscribe to them in AppDelegate. It was discussed here
    @main
    struct YourApp: App {
        @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
        var body: some Scene {
            WindowGroup {
                ContentView()
            }
        }
    }
    

    AppDelagate

    // AppDelegate.swift
    class AppDelegate: NSObject, UIApplicationDelegate {
        func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
            UNUserNotificationCenter.current().delegate = self
            return true
        }
    }
    
    extension AppDelegate: UNUserNotificationCenterDelegate {
        func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
            // Here we actually handle the notification
            print("Notification received with identifier \(notification.request.identifier)")
            // So we call the completionHandler telling that the notification should display a banner and play the notification sound - this will happen while the app is in foreground
            completionHandler([.banner, .sound])
        }
    }