I am following the push notification tutorial here: https://www.raywenderlich.com/11395893-push-notifications-tutorial-getting-started
I've gotten everything working on a test device, and after allowing notifications, I can get the device token when didRegisterForRemoteNotificationsWithDeviceToken runs.
Now I want to change when I ask for notification permissions. I don't want to ask the user permission for notifications on app launch, as in the tutorial. I only want to ask later on, once the user has logged in. However, when I call the AppDelegate to register for notifications, it prompts the user, but when they accept, it doesn't run the didRegisterForRemoteNotificationsWithDeviceToken function, which has the device token I need to send to my back end. What gives?
AppDelegate.swift
import SwiftUI
import UserNotifications
class AppDelegate: NSObject, UIApplicationDelegate {
@EnvironmentObject var authenticatedUser: AuthenticatedUser
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
return true
}
func registerForPushNotifications() {
UNUserNotificationCenter.current()
.requestAuthorization(
options: [.alert, .sound, .badge]) { [weak self] granted, _ in
print("Permission granted: \(granted)")
guard granted else { return }
self?.getNotificationSettings()
}
}
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { settings in
print("Notification settings: \(settings)")
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
// this function never gets called!
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
print("Device Token: \(token)")
// send token to backend here
}
func application(
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error
) {
print("Failed to register: \(error)")
}
}
MyGroupView.swift where I want to prompt for notification permission
import SwiftUI
struct MyGroupView: View {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@EnvironmentObject var authenticatedUser: AuthenticatedUser
// other variables and state here...
var body: some View {
GeometryReader { proxy in
VStack {
// content here...
}
.onAppear() {
appDelegate.registerForPushNotifications()
}
.edgesIgnoringSafeArea(.bottom)
}
}
// other functions...
}
In your AppDelegates didFinishLaunchingWithOptions
you need to set the delegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
UNUserNotificationCenter.current().delegate = self
return true
}