从 App Delegate 调用 ViewControllers 方法或 Segue (Swift)

Call ViewControllers Method or Segue from App Delegate (Swift)

我创建了一个使用情节提要的应用程序,并成功创建了一个表格视图和详细信息页面,一切正常。

我希望这样可以将滑动 localNotifications 的用户发送到应用内正确的详细信息页面。

看来我可以从 ViewController 调用函数,但每当它们引用自己更新任何详细信息或执行 segue 时,应用程序就会崩溃。

我的 ViewController 中的代码如下:

func handleMessageNotification (messageID:String)
{
    // this function should act as a conduit for the call from the delegate
    println("notif messageID: \(messageID)");
    self.performSegueWithIdentifier("showMessageDetail", sender: self);
    self.messageView.reloadData();
}

这是从我的 appDelegate 调用的

func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
  if (application.applicationState == UIApplicationState.Background || application.applicationState == UIApplicationState.Inactive)
    {
        var rootViewController = self.window!.rootViewController
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        var setViewController = mainStoryboard.instantiateViewControllerWithIdentifier("ViewController") as ViewController
        rootViewController?.navigationController?.popToViewController(setViewController, animated: false)
        setViewController.handleMessageNotification(messageID);
  }
}

println 工作正常但 performSegue 失败(致命错误:在展开可选值时意外发现 nil)并且 messageView.reload() 失败(同样的错误)。

如何在打开时收到将应用程序触发到正确位置的通知?

此解决方案“Get Instance Of ViewController From AppDelegate In Swift”使用的大部分内容相同,但我的解决方案不允许使用 ViewController.

访问任何内容

=======更新-解决方案=======

对于遇到此问题的其他人。根据 Gabuh 在下面的建议;对我来说,完整的解决方案是执行以下操作:

func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
    if (application.applicationState == UIApplicationState.Background || application.applicationState == UIApplicationState.Inactive)
    {
        let navigationController = application.windows[0].rootViewController as UINavigationController;
        navigationController.popToRootViewControllerAnimated(false); // I need to push back to root before performing segue
        let rootViewController = navigationController.visibleViewController;
        rootViewController.performSegueWithIdentifier("showMessageDetail", sender: self);
    }
}

这也允许我调用视图中的函数,例如在原始示例中

rootViewController.handleMessageNotificaion(messageID);

rootViewController.messageView.reloadData();

您正在创建新 ViewController 的实例。当 ViewController 甚至没有显示时,您正试图在 ViewController 上调用一个函数,该函数试图执行一个 segue。我认为这行不通...

如果您想从详细视图执行转场,您必须访问当前实例化的视图控制器并从中执行转场。

如果您想知道如何获取正在显示的 UIViewController 的实例,在此 post 中有几种方法可以向您展示如何做到这一点:

Get the current view controller from the app delegate

在伪代码中,在您的 appDelegate 中:

1- 获取当前 UIViewController 实例(不是新实例)

2- 从该视图控制器执行 segue(或模态呈现或您想要的任何过渡)

在Swift 3:

    guard let rvc = self.window?.rootViewController as? VCName else { return }
    rvc.methodInYourVC()

以上假设

  1. 您不想创建 VCName 的全新实例,只想引用它
  2. 您知道要引用的 VC 是您的根 VC