点击本地通知打开特定的视图控制器

open specific view controller upon tapping local notification

标题说明了一切。我浏览了很多帖子,试图找到一个解决方案,但没有成功..

我有一个通知,我不确定其名称...

let request = UNNotificationRequest(identifier: "timerDone", content: content, trigger: trigger)

q1: 名字是timerDone?

viewDidLoad() 中:

NotificationCenter.default.addObserver(self,
                                                         selector: "SomeNotificationAct:",
                                                         name: NSNotification.Name(rawValue: "timerDone"),
                                                         object: nil)

然后我有这个方法:

@objc func SomeNotificationAct(notification: NSNotification){
        DispatchQueue.main.async() {
            self.performSegue(withIdentifier: "NotificationView", sender: self)
        }
    }

AppDelegate.swift中的这个:

private func application(application: UIApplication, didReceiveRemoteNotification userInfo: Any?){

    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "SomeNotification"), object:nil)
}

有什么办法吗?提前致谢!

更新:@Sh_Khan

首先,我在 swift 中编码,我尝试将您的代码从 obj-c 翻译成 swift 为:

if (launchOptions![UIApplicationLaunchOptionsKey.localNotification] != nil)
{
    var notification =
        launchOptions![UIApplicationLaunchOptionsKey.localNotification]
    [self application:application didReceiveLocalNotification:notification]; //how to translate?
}

最后一行应该翻译成什么?

当你写道:

应该在 didReceiveLocalNotification 方法中的用户默认值中存储一个布尔变量,并在 rootViewcontroller 的 viewDidAppear 方法中检查它以进行转场,然后将其设为 false,因为通知中心仅在应用程序处于前台时才工作或者在后台,如果它还没有暂停

假设布尔值是 notiView 并且我们在收到本地通知时将其设置为 true ,因此 segue 将转到 不同的 视图控制器。这是你的意思吗?

如果应用程序已关闭并且您点击了本地通知,请在 didFinishLaunchingWithOptions 方法中检查它

/// Objective-C

if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey] != nil)
{
  UILocalNotification *notification =
  launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
 [self application:application didReceiveLocalNotification:notification];
}

/// Swift

if (launchOptions![UIApplicationLaunchOptionsKey.localNotification] != nil)
{     

    var notification =
    launchOptions![UIApplicationLaunchOptionsKey.localNotification]

   self.application(application, didReceive: notification)
}

注意: rootViewcontroller 的viewDidLoad 还没有被调用所以观察者不会被触发,所以你应该存储一个didReceiveLocalNotification 方法中用户默认值中的布尔变量,并在 rootViewcontroller 的 viewDidAppear 方法中检查它以进行转场,然后进行 false 因为 notificationCenter 仅在应用处于 foreground 或处于 background 时(如果尚未暂停)工作。 . .

更新:@Shi_Zhang

是的,就是这个意思

我发现用户通知文档有点混乱和不完整。这些教程比大多数其他 Apple 框架都要好。然而,这些教程大多是不完整的,并且假设每个应用程序都在 AppDelegate 中实现了通知中心委托。不是!

对于许多在视图控制器中(而不是在 AppDelegate 中)处理通知委托的应用程序,需要在 AppDelegate didFinishLaunchingWithOptions 方法中将视图控制器设置为用户通知中心委托。否则,当您的应用程序从后台模式启动时,通知代理将看不到您的通知触发。您的视图控制器在通知触发后加载。您需要一种在视图控制器完成加载后启动委托方法的方法。

例如:假设您使用拆分视图控制器作为您应用程序的初始视图控制器,并且您已经将拆分 VC 的主视图控制器实现为您的通知代理,您需要让当您的应用程序启动时,UNUserNotificationCenter 知道 master VC 是它的委托(不像大多数教程所建议的那样在 master VC 的 viewDidLoad() 内部)。例如,

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        ...
        let splitViewController = window!.rootViewController as! UISplitViewController
        ...
        if #available(iOS 10.0, *) {
            if let masterViewController = splitViewController.viewControllers.first as? MasterViewController {
                UNUserNotificationCenter.current().delegate = masterViewController
            }
        }
    }

当您的应用冷启动或从后台模式启动时,这将允许 iOS 在主 VC 加载后调用您的通知委托方法。

此外,如果您需要您的主人 VC 知道它是因为用户通知触发而加载的(而不是正常加载),您将使用 NSUserDefaults 来传达此信息。因此,AppDelegate 将如下所示:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    ...
    let splitViewController = window!.rootViewController as! UISplitViewController
    ...
    if #available(iOS 10.0, *) {
        if let _ = launchOptions?[UIApplicationLaunchOptionsKey.localNotification] {
            UserDefaults.standard.set("yes", forKey: kMyAppLaunchedByUserNotification)
            UserDefaults.standard.synchronize()
        }
        if let masterViewController = splitViewController.viewControllers.first as? MasterViewController {
            UNUserNotificationCenter.current().delegate = masterViewController
        }
    }
}

其中 kMyAppLaunchedByUserNotification 是您用来与主机通信的密钥 VC。在 Master View Controller 的 viewDidAppear() 中,您将检查 User Defaults 以查看它是否因通知而被加载。

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    if #available(iOS 10.0, *) {
        if let _ = UserDefaults.standard.object(forKey: kMyAppLaunchedByUserNotification) {
            UserDefaults.standard.removeObject(forKey: kMyAppLaunchedByUserNotification)
            UserDefaults.standard.synchronize()
            //Handle any special thing that you need to do when your app is launched from User notification as opposed to regular app launch here
            // NOTE: the notification delegate methods will be called after viewDidAppear() regardless of you doing any special thing here because you told iOS already in AppDelegate didFinishLaunchingWithOptions
        }
    }
}

希望对你有所帮助。