简体   繁体   中英

responding to push notification when app is TERMINATED

As I am very new to push notifications I have looked at several tutorials that outline the best way to handle remote push notifications when app is terminated and it seems that I still have an issue in my app. I am calling didFinishLaunchingWithOptions when push notification is tapped but for some reason the function is skipped over and does not execute the code to open the proper view controller.

Here is the code in AppDelegate

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
// Override point for customization after application launch.

//UserNotification
let center = UNUserNotificationCenter.current()

center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
    // Enable or disable features based on authorization.
    if granted {
        UIApplication.shared.registerForRemoteNotifications()

        if GlobalService.sharedInstance().g_userDeviceToken == nil {
            //  GlobalService.sharedInstance().g_userDeviceToken = ""


        }
    } else {
        print("Don't Allow")

    }

    if let notification = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [String: AnyObject] {

        self.getUserChatRooms()
        let aps = notification["aps"] as! [String: AnyObject]

        let mainNC = self.window?.rootViewController as! UINavigationController
        let storyboard = UIStoryboard.init(name: "Main", bundle: nil)

        let mainVC = storyboard.instantiateViewController(withIdentifier: String(describing: MainViewController.self)) as! MainViewController
        GlobalService.sharedInstance().g_homeVC = mainVC
        mainVC.didReceiveChat(aps)
        mainNC.pushViewController(mainVC, animated: false)

    }
    ...

//SVProgressHUD
SVProgressHUD.setDefaultStyle(.dark)

//Check UserObj
GlobalService.sharedInstance().g_appDelegate = self
if let userObj = GlobalService.sharedInstance().loadUserObj() {
    GlobalService.sharedInstance().g_userMe = userObj
    startApplication(animated: false)
...
return true
}

then this is the function that is called in MainVC:

  func didReceiveChat (_ notificationDictionary: [String: AnyObject]){
let allChats = GlobalService.sharedInstance().g_aryChatRooms

if let noti_id = notificationDictionary["noti_id"] as? String{
        let pushID = Int(noti_id)
    if pushID != nil {
        for chat in allChats {

            if chat.chat_room_id! == pushID! {
            chtRoom = chat

                 NotificationCenter.default.post(name: Notification.Name(rawValue: Constants.Notifications.GET_MSG), object: self)
            break
            }
        }
    }
}
 }

and then in my viewDidLoad method I add the observer:

    NotificationCenter.default.addObserver(self,selector: #selector(MainViewController.addChatScn(_:_:)), name: NSNotification.Name(rawValue: Constants.Notifications.GET_MSG), object: nil)

finally I call the method to addChatScn:

  @objc func addChatScn(_ chatObj: ChatRoomObj, _ msgName: String) {
    let popvc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ChatContainerViewController") as! ChatContainerViewController

    iconContainer.isHidden = true
    add_Msg_Btn.isHidden = true
    popvc.vcA = self
    popvc.m_selectedChatRoom = chatObj
    popvc.msgName = msgName
    self.addChildViewController(popvc)
    popvc.view.center = self.view.center
    popvc.view.bounds.size = CGSize(width: 337, height: 503)

    self.view.addSubview(popvc.view)

    popvc.didMove(toParentViewController: self)
}

In your GlobalService.sharedInstance, Add a boolean value called 'readyToReceivePush'. In your MainVC in your viewDidLoad, set the 'GlobalService.sharedInstance.readyToReceivePush' to true. Set it to false if the app goes into the background, and true if it comes back to foreground.

func applicationDidEnterBackground(_ application: UIApplication) {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    GlobalService.sharedInstance.readyToReceivePush = false
}

func applicationWillEnterForeground(_ application: UIApplication) {
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    GlobalService.sharedInstance.readyToReceivePush = true
}

Once you have that set up, if the user swipes on a notification the 'didReceiveRemoteNotification' will be called. In that method, if GlobalService.sharedInstance.readyToReceivePush == false, save the userInfo to GlobalService.sharedInstance.savedPushInfo.

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    if GlobalService.sharedInstance.readyToReceivePush == false {
        GlobalService.sharedInstance.savedPushInfo = userInfo
    } else {
        // Handle notification while the user is in the foreground
    }
}

Once you've done that, in MainVC check if GlobalService.sharedInstance.savedPushInfo != nil. If it is != nil, call your 'didReceiveChat' function or whatever you do to handle the notification's userInfo data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM