简体   繁体   中英

Call ViewControllers Method or Segue from App Delegate (Swift)

I have created an app that uses storyboard and have successfully created a tableview and detail page which all works.

I would like it so that users swiping the localNotifications can be sent to the correct detail page within the app.

It appears that I can call functions from the ViewController but whenever they refer to themselves to update any details or perform a segue the app crashes.

The code i have in my ViewController is as follows:

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();
}

and this is called from my 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);
  }
}

the println works correctly but performSegue fails (fatal error: unexpectedly found nil while unwrapping an Optional value) and the messageView.reload() fails (same error).

How do I get a notification to fire the app to the correct place upon opening?

This solution ' Get Instance Of ViewController From AppDelegate In Swift ' uses much of the same but mine will not allow access to anything with the ViewController.

======= Update - Solution =======

For anyone else with this issue. Following on from what Gabuh had suggested below; the full solution for me was to do the following:

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

this also allows me to make calls on functions in the view such as in the original example eg

rootViewController.handleMessageNotificaion(messageID);

or

rootViewController.messageView.reloadData();

You are creating an instance of a new ViewController . And you are trying to call a function on that ViewController, that is trying to perform a segue, when the ViewController is not even displayed. I think that's not going to work...

If you want to perform a segue from your detail view, you have to access to the current instantiated view Controller and perform the segue from it.

If you want to know how to get the instance of the UIViewController that is being displayed, in this post there are several ways that show you how to do it:

Get the current view controller from the app delegate

In pseudo-code, in your appDelegate:

1- get current UIViewController instance (not new one)

2- perfom segue from that view controller (or present modally or whatever transition you want)

In Swift 3:

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

The above assumes

  1. That you don't want to create a whole new instance of VCName, just want a reference to it
  2. That you know the VC you want to reference is your root VC

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