Search code examples
iosswiftuiapple-push-notifications

SwiftUI prompt notification permission in second view


I have 2 view in my project which is login and home view. I tried to prompt notification permission in the home view after the user successful login. After I tried, I found the Push Notification for Beginner. The permission prompt while the application first launch in the login view. Is there any way to set the view of the permission agreement?

struct ContentView: View {
    @EnvironmentObject var authService:AuthService

    var body: some View{
        ZStack{
            if(!authService.signedIn){
                RegisterView()
            }
            else{
                HomePageView() //The view I want to ask for permission after signedIn
            }
        }
    }
}
import UIKit
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        let auth = UserDefaults.standard.object(forKey: "Auth")
        //if auth != nil {
        //    registerForPushNotifications()
        //}  //what I tried, but It prompt while user restart the app after login.
        registerForPushNotifications()
        return true
    }

    // MARK: UISceneSession Lifecycle

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }

    func registerForPushNotifications() {
      //1
      UNUserNotificationCenter.current()
        //2
        .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()
        }

      }
    }
    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)")
    }
}


Solution

  • Actually, you are requesting notification access, when the user launches the app (inside application(_:, didFinishLaunchingWithOptions:). you have to call your registerForPushNotifications method, after a successful login.

    for example:

            // successful login
            // e.g: authService..signedIn = true
            (UIApplication.shared.delegate as? AppDelegate).registerForPushNotifications()