segmentio / segment-docs

Segment Documentation. Powered by Jekyll.
https://segment.com/docs/
Creative Commons Attribution 4.0 International
46 stars 325 forks source link

[Content]: Mobile Push Onboarding - SwiftUI #5862

Open bf2344 opened 5 months ago

bf2344 commented 5 months ago

What article on segment.com/docs is affected?

https://segment.com/docs/engage/campaigns/mobile-push/

What part(s) of the article would you like to see updated?

We are currently researching implementing Mobile Push Notifications into our iOS app. Currently all the of the docs are for using Swift and UIKit.

here is an example from the documentation that would not work for SwiftUI

To start receiving and handling mobile push notifications, add or modify the following methods in your AppDelegate:

   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    //Add the following:

        let center  = UNUserNotificationCenter.current()
        center.delegate = self
        center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
            guard granted else {
                Analytics.main.declinedRemoteNotifications()
                Tab1ViewController.addPush(s: "User Declined Notifications")
                return
            }
            DispatchQueue.main.async {
                UIApplication.shared.registerForRemoteNotifications()
            }
        }

        // The following conditional statement is necessary to handle remote notifications in older versions of iOS.
        if let notification = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] as? [String: Codable] {
            Tab1ViewController.addPush(s: "App Launched via Notification \(notification)")
            Analytics.main.receivedRemoteNotification(userInfo: notification)
        }

        ...

        return true
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    // Segment event to register for remote notifications
    Analytics.main.registeredForRemoteNotifications(deviceToken: deviceToken)
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    // Segment event for failure to register for remote notifications
    Analytics.main.failedToRegisterForRemoteNotification(error: error)
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) async -> UIBackgroundFetchResult {
    // Segment event for receiving a remote notification
    Analytics.main.receivedRemoteNotification(userInfo: userInfo)

    // TODO: Customize notification handling based on the received userInfo.
    // Implement actions or UI updates based on the notification content.

    return .noData
}

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async {
    let userInfo = response.notification.request.content.userInfo
    //Segment event for receiving a remote notification
    Analytics.main.receivedRemoteNotification(userInfo: userInfo)

    // TODO: Customize notification response handling based on the received userInfo.
    // Implement actions based on the user's response to the notification.
    // Example: Navigate to a specific screen or perform an action based on the notification.

}

The app.delegate file does not exist in SwiftUI applications.

Perhaps you already have an update in the works, but just wanted to surface this as SwiftUI is the newest development framework released.

Additional information

No response

JedediahAlax commented 5 months ago

@bf2344 here is how I implemented it within a SwiftUI app. Although there is no App Delegate file we can create a class called AppDelegate that conforms to NSObject, UIApplicationDelegate, and UNUserNotifcationCenterDelegate protocols

class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        //Add the following:

            let center  = UNUserNotificationCenter.current()
            center.delegate = self
            center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
                guard granted else {
                    Analytics.main.declinedRemoteNotifications()
                   // Tab1ViewController.addPush(s: "User Declined Notifications")
                    return
                }
                DispatchQueue.main.async {
                    UIApplication.shared.registerForRemoteNotifications()
                }
            }

            // The following conditional statement is necessary to handle remote notifications in older versions of iOS.
            if let notification = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] as? [String: Codable] {
                //Tab1ViewController.addPush(s: "App Launched via Notification \(notification)")
                Analytics.main.receivedRemoteNotification(userInfo: notification)
            }

            return true
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // Segment event to register for remote notifications
        Analytics.main.registeredForRemoteNotifications(deviceToken: deviceToken)
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        // Segment event for failure to register for remote notifications
        Analytics.main.failedToRegisterForRemoteNotification(error: error)
    }

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) async -> UIBackgroundFetchResult {
        // Segment event for receiving a remote notification
        Analytics.main.receivedRemoteNotification(userInfo: userInfo)

        // TODO: Customize notification handling based on the received userInfo.
        // Implement actions or UI updates based on the notification content.

        return .noData
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async {
        let userInfo = response.notification.request.content.userInfo
        //Segment event for receiving a remote notification
        Analytics.main.receivedRemoteNotification(userInfo: userInfo)

        // TODO: Customize notification response handling based on the received userInfo.
        // Implement actions based on the user's response to the notification.
        // Example: Navigate to a specific screen or perform an action based on the notification.

    }
}

This class can be created in the App file of a SwiftUI project. We also need to add the delegate so place @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate in the App file as well.

github-actions[bot] commented 3 months ago

This issue is stale because it has been open 60 days with no activity.