【问题标题】:Swift IOS: Call Specific function of UIviewController when open app from notificationSwift IOS:从通知打开应用程序时调用 UIviewController 的特定功能
【发布时间】:2019-02-26 12:00:05
【问题描述】:

我想在应用程序打开时通过点击通知调用onDidReceiveNotification 函数。 (ViewController 是第一个视图控制器,根视图控制器)

当应用程序打开或在后台运行正常,但是当应用程序未打开或在后台(不在内存中)并点击打开应用程序时onDidReceiveNotification函数未被调用,

当应用程序通过点击推送通知打开时,我应该怎么做才能调用onDidReceiveNotification函数

ViewController.swift

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        NotificationCenter.default.removeObserver(self, name: .didReceiveAlert, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(ViewController.onDidReceiveNotification(_:)), name: .didReceiveAlert, object: nil)
    }

@objc func onDidReceiveNotification(_ notification:Notification) {
        print("Received Notification")
    }
}

AppDelegate.swift

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {            
    NotificationCenter.default.post(name: .didReceiveAlert, object: nil)       
}

【问题讨论】:

  • 我认为这是预期的行为,如果应用程序关闭,您需要检查 appdelegate 中 didFinishLaunchingWithOptions 中的 launchOptions 方法以获取收到的通知详细信息。
  • didReceiveRemoteNotification 在应用关闭并使用通知打开时调用
  • 查看let remoteNotif = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [String: Any]的应用启动远程通知
  • 好的,例如我已经签入了launchOptions,我知道应用程序已使用通知打开,但是之后如何在视图控制器中调用我的函数“onDidReceiveNotification”

标签: ios swift push-notification apple-push-notifications nsnotificationcenter


【解决方案1】:

当应用程序打开或在后台调用 NotificationCenter.defalut.post 时,当应用程序终止/关闭并使用通知打开时,获取实例并通过菜单调用 onDidReceiveAlert 函数,请参见以下代码。

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

    if application.applicationState == .background || application.applicationState == .active {
        NotificationCenter.default.post(name: .didReceiveAlert, object: nil)
    }else {
        let nav = window?.rootViewController as! UINavigationController
        let mainVC = nav.viewControllers.first as! ViewController
        mainVC.onDidReceiveAlert(nil)
    }
}

或者直接从UINavigationController栈中获取ViewController实例,直接调用ViewController的函数(Notification Observer不需要)

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

    let nav = window?.rootViewController as! UINavigationController
    let mainVC = nav.viewControllers.first as! ViewController
    mainVC.onDidReceiveAlert(nil)       
}

使用可选参数创建函数,使用以下代码。

@objc func onDidReceiveAlert(_ notification:Notification? = nil) {
    print("Received Notification")
}

【讨论】:

    【解决方案2】:

    试试下面的代码

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        if let remoteNotif = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [String: Any] {
             //call your notification method from here
             NotificationCenter.default.post(name: .didReceiveAlert, object: nil)  
        }
    }
    

    希望您在所有情况下都只需要调用didReceiveAlert 通知

    【讨论】:

      【解决方案3】:

      在 AppDelegate 中检查您是否在 didReceiveRemoteNotification 中获得了有效负载。从那里您可以编写代码以推送到特定页面。

      func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
          // Print full message.
          print(userInfo)
          pushToPage(data: userInfo)
      }
      
      func pushToPage(data:[AnyHashable : Any]){
          print("Push notification received: \(data)")
          if let aps = data["aps"] as? NSDictionary {
              print(aps)
          }
      }
      

      【讨论】:

        【解决方案4】:

        当应用处于非活动状态并且用户点击通知时。在这种情况下,只有一个选项来管理通知。

        试试这个

        在全局类中创建一个变量,以便您可以从任何地方访问它。

        ExAppDelegate中创建变量

        var isNotificationTap : Bool = false
        

        然后检查launchOptions,如果launchOptions 可用,则设置标志

        if launchOptions != nil {
            if let userInfo = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] as? [String : AnyObject] {
                if let dic = userInfo["body"] as? [String : AnyObject] {
                    if let pushType = dic["push_type"] as? String {
                        //Set Flag or any key in global file to identify that you tap on notification
                        self.isNotifcaionTap = true
                    }
                }
            }
        }
        

        然后只需检查 ViewController 中的标志。

        class ViewController : UIViewController {
        
            override func viewDidLoad() {
                super.viewDidLoad()
        
                if self.isNotificationTap {
        
                    print("Received Notification")
                    //You can work with your notificaiton in inActive state
                }
            }
        
        }
        

        【讨论】:

        • 我不想使用全局变量,这是一种非常低质量的方法,有没有其他方法
        • 推送通知处于非活动状态的主要问题是我们只有在 didFinishLauching 启动选项上跟踪非活动通知点击的选项,并且我们没有 rootViewController 来管理通知流。所以我们只能选择设置 key 或 flag 来管理。
        猜你喜欢
        • 1970-01-01
        • 2013-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多