In iOS, developers can create and send user notifications locally or remotely from a server through the Apple Push Notification Service (APNs). Enabling remote push notifications in iOS apps requires setting up a server to communicate with the APNs for a production app. However, using the simulator, you can quickly emulate and debug remote push notifications without APNS and a company server. Keep reading to learn how to configure and debug push notifications using the iOS simulator and your favorite command line tool.
Go Further
This article is a general overview tutorial for creating and testing remote push notifications using an iOS simulator. Check out the following resources to dive deep into regular and VoIP push notifications on iOS.
- Remote Push Notifications: Stream Chat iOS
- Regular and VoIP Push Notifications: Stream Video iOS
- VoIP Push Notifications using PushKit.
The completed SwiftUI demo project is available in our tutorial projects repository on GitHub. Download and test the alert push notification using a simulator and your favorite command line tool.
User Notifications Overview
Due to the events and updates in your iOS app, you may deliver up-to-date information to the user's device when the app is in the background or foreground. These user-facing notifications can communicate timely information regardless of the app's state, whether active or inactive. The content of a notification can include an alert, sound, and a badge for a visible notification. The diagram above illustrates the types of user notifications you can schedule to trigger locally through your app or remotely via communication between a provider server and APNs.
Benefits of User Notifications
- Send real-time notification updates to your app. For example, an audio room app may alert participants when a new user joins an ongoing audio room conversation.
- Power efficiency: User-facing notifications are power efficient. Sometimes, an app cannot deliver notifications when the battery level runs low. For example, if a new iOS version is available to download and install, the system can only install it if the battery is at least 50%. That is purposely done to save the battery of the device.
- Push notifications create dynamic experiences. Particularly, alert pushes support interactivity, such as tapping to view details or using a flick gesture to dismiss the notification before it disappears. Users can tap and hold notifications to display a longer view without opening the app.
- Support for background and foreground: An app to receive push notifications does not necessarily need to be running or inactive.
- Easily customizable: Developers can customize visible push notifications' look, feel, and interaction styles.
Alert and Silent Notifications Overview
As demonstrated in the diagram above, local or remote notification can be delivered as a background notification (silent notification) or an alert notification. Background notifications do not have a visible UI because they notify the app, not the users. However, notifications delivered via alerts are visible to users.
Silent notifications are used for background app refresh, such as downloading information to keep the app up-to-date. Additionally, these notifications rely upon the device's power and time to decide the delivery of notifications.
Alert Push Notifications
The app’s users can interact with these visible alerts in various ways. The purpose of these notifications is to inform users about new information they can interact with. In a video conferencing app like Zoom, push notifications are used to notify meeting participants when another call participant joins or leaves the meeting.
Similarly, in a live streaming app like Twitch or an audio room app like Club House, push notifications are used to inform guests when the room or stream goes live.
Visible alerts (notifications) do not require the app to run before they can be delivered. For example, when a user sends a chat app to the background and launches a video calling app, the chat app can still receive real-time data while in the background.
Background Push Notifications
These notifications are not displayed using sound or a badge. They are server-based and inform the app about necessary updates. Delivering background notifications does not require setting user permissions or sending an approval request.
Alert Notification Content
A typical alert notification consists of:
- Content: The title and a short description of the type of notification you want to display to users.
- Trigger: When and how to show the notification.
- Request: Registers the notification content and triggers to the system.
The content of the notification is called a payload. The payload contains the information you want to deliver to users as a notification. You can construct the notification payload with a series of fields using a JSON dictionary.
Note: The maximum size of a regular remote notification payload cannot exceed 4KB. Similarly, the payload size for VoIP notifications cannot exceed 5KB.
Create the Remote Notification Payload
The code snippet below demonstrates the typical structure of a push notification payload and its parts. It is an example notification payload with an alert dictionary for a video-conferencing application that alerts participants whenever a team member joins a meeting call.
{ "aps" : { "alert" : { "title" : "All Hands", "body" : "Amos has joined the meeting" }, "sound" : "default", "badge" : 10, }, "duration": "Current time", "startedAt": "Meeting’s starting time" }
An alert notification payload consists of an aps
dictionary. The aps
dictionary contains Apple-defined keys and information about how to render the notification. The alert
dictionary contains a title field and a short, human-readable notification description. The sound
field is optional. You can specify this field to play audio when the app receives a notification. The sound
field can use the specified default or a custom sound. Like the sound
field, the badge
is optional. It is an absolute value for overriding the app’s icon. The other fields can be used to specify custom data. In this example, the duration of the meeting and its starting time are custom data fields.
For our demo notification app to be able to recognize the payload and display the alert notification using a simulator, it is required to specify the app's Bundle Identifier in the payload. The bundle identifier should be placed above the aps
dictionary "Simulator Target Bundle": "com.amosgyamfi.AlertPushNotifications"
.
Create a Payload With an Alert String
Instead of describing a visible notification alert with a dictionary, you can use a string, as shown in the snippet below.
{ "Simulator Target Bundle": "com.amosgyamfi.AlertPushNotifications", "aps": { "alert": "Amos has joined the meeting!", "sound": "default", "badge": 1 } }
To create a JSON dictionary for our notification app's payload, follow the instructions below. Start with a new SwiftUI project in Xcode.
- Press Control on the keyboard and click anywhere in the Xcode Project bundle to add a new JSON file.
- Select GeoJSON File from the dialog window.
- Name the file, for example, AlertPushNotification, and follow the next instructions to create it.
- Xcode will add the extension .geojson to the file. Change the extension to .apns. The file name in step 3 above becomes AlertPushNotification.apns. The file is a certificate for the Apple Push Notification service (APNs)
- Finally, replace the file's content with the sample snippet below.
{ "Simulator Target Bundle": "com.amosgyamfi.AlertPushNotifications", "aps" : { "alert" : { "title" : "All Hands", "body" : "Amos has joined the meeting" }, "sound" : "default", "badge" : 10, }, "duration": "Current time", "startedAt": "Meeting’s starting time" }
Configure Your App For Alert Notifications
You can configure your app to send and display remote alert notifications for inactive and active app states. The delivered notification may appear on the device's lock screen, Dynamic Island, Notifications Center, or from the top edge of the device's screen. The first step is registering the device to receive pushes from APNs. In this case, setting up APNs requires communicating with your provider server to send notifications.
This article will focus mainly on testing remote notifications using the iOS simulator. A later article will cover using APNs to send and receive remote notifications. Let’s create a new SwiftUI app, AlertPushNotifications. Follow the steps below to configure the remote notifications.
- Declare
UNUserNotificationCenterDelegate
inAppDelegate
. Doing so will assign your AppDelegate as a delegate of the notification center and will notify the app when a user opens the alert. SwiftUI does not implement anAppDelegate
by default, so you should implement it in the app's conformer file.
123456class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate { func application (_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { registerForNotifications() return true } }
- Ask the user's permission to show alert notifications by calling the
requestAuthorization
method.
12345678// MARK: Request user permissions func registerForNotifications() { UNUserNotificationCenter.current() .requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in print("Permission granted: \(granted)") } }
- Set up registration callback functions to check whether the registration fails or succeeds and display the notification.
123func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.banner, .sound]) }
- Connect the
AppDelegate
class to the SwiftUI app’s lifecycle@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
.
Let’s combine all the steps above in the main SwiftUI project file AlertPushNotificationsApp.app.
12345678910111213141516171819202122232425262728293031323334353637383940414243// // AlertPushNotificationsApp.swift // AlertPushNotifications import UIKit import SwiftUI import UserNotifications // Step 1. Declare `UNUserNotificationCenterDelegate` class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate { func application (_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { registerForNotifications() return true } // Step 2. Ask the user's permission to show alert notifications by calling the `requestAuthorization` method. func registerForNotifications() { UNUserNotificationCenter.current() .requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in print("Permission granted: \(granted)") } } // Step 3. Set up registration callback functions to check whether the registration fails or succeeds and display the notification. func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.banner, .sound]) } } // MARK: Connect the app delegate to the SwiftUI app lifecycle @main struct AlertPushNotificationsApp: App { // Step 4. Connect the `AppDelegate` class to the SwiftUI app’s lifecycle @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var body: some Scene { WindowGroup { ContentView() } } }
Test the Alert Notification With an iOS Simulator
At this point, we have set up the remote notification with the AppDelegate class and created a payload to show the notification. It is now time for the exciting moment: testing.
Run the app and place the running simulator on the side of the Xcode's window.
Lock the device screen of the simulator by pressing cmd + l to show the home screen.
Drag your APNs certificate file AlertPushNotification.apns to the simulator.
Bravo! You can now see the notification displaying with a default sound.
Specify a Custom Notification Sound
The above alert notification example uses the iOS default sound when displaying the notification. To provide a custom notification sound experience:
- Add an audio file with an extension .mp3, .aiff, or .m4a to the Xcode’s project bundle. The example in this section uses a -5dB notification sound from Meta’s Sound Kit.
- Specify the custom sound AlertSound.m4a in the payload as shown below.
{ "Simulator Target Bundle": "com.amosgyamfi.AlertPushNotifications", "aps": { "alert": "Amos has joined the meeting!", "sound": "AlertSound.m4a", "badge": 1 } }
Now, dragging the APNs certificate file AlertPushNotification.apns to the simulator will play the custom sound when displaying the alert.
How to Send Notifications Through the Command Line
You can send push notifications using your favorite command line tool, such as Terminal or Warp. Follow the steps below to configure and receive alert pushes through the terminal.
- Get the iOS simulator’s identifier from Xcode. Go to the Toolbar and click Window -> Devices and Simulators.
- Find the identifier of the selected iOS simulator under the Simulators tab. Select and the identifier
92BE6788-0D03-4801-AAA0-C3A42EB92790
.
- Obtain the bundle identifier of the project
com.amosgyamfi.AlertPushNotifications
. Select the main app’s folder and click General to find the project’s bundle ID.
- Specify the path of the alert notification payload file
/Users/amos.gyamfigetstream.io/Desktop/StreamDevRel/2024/AlertPushNotifications/AlertPushNotifications
. Navigate to the Xcode project’s source folders, find the payload file, and copy its path.
- Run the following command in Terminal or Warp
xcrun simctl push 92BE6788-0D03-4801-AAA0-C3A42EB92790 com.amosgyamfi.AlertPushNotifications Desktop/StreamDevRel/2024/AlertPushNotifications/AlertPushNotifications/AlertPushNotification.apns
.
The command above is used to send the payload via the command line and communicate with the selected iOS simulator.
After sending the command, the alert push notification will display from the top edge of the simulator with a sound and disappear after a few seconds.
What's Next?
This article introduced you to using the iOS simulator in testing and sending remote push notifications. It covered the creation of a notification payload and testing it through the command line to display alert notifications. Check out the related links to learn more about push notifications for chat messaging and iOS Voice Over IP (VoIP) apps.