Swift - pushViewController from appDelegate, rootV

2019-03-10 22:57发布

Having a problem following a few guides, specifically http://blog.originate.com/blog/2014/04/22/deeplinking-in-ios/

I'm setting the url scheme and it's working well to launch the app from another app, but passing in the host or url are not working as it seems it should. I'm using storyboards and interface builder for all the view layouts.

The guide shows this openURL in appDelegate:

-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
    if([[url host] isEqualToString:@"page"]){
        if([[url path] isEqualToString:@"/page1"]){
            [self.mainController pushViewController:[[Page1ViewController alloc] init] animated:YES];
        }
    return YES;
    }
}

Here is my version simplified and in swift from a few other sources, ie Get Instance Of ViewController From AppDelegate In Swift I'm skipping the conditional for the url host at the moment to remove potential other variables in the problem.

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String, annotation: AnyObject?) -> Bool {
    var rootViewController = self.window!.rootViewController
    let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    var profileViewController = mainStoryboard.instantiateViewControllerWithIdentifier("profile") as ProfileViewController

    rootViewController.navigationController.popToViewController(profileViewController, animated: true)

    return true

}

The swift version causes a crash: fatal error: unexpectedly found nil while unwrapping an Optional value

It seems that rootViewController doesn't have a navigationController yet?

6条回答
够拽才男人
2楼-- · 2019-03-10 23:27

SWIFT 4: Safe way to push with the use of conditional binding and Chaining

if let navController = self.navigationController, let viewController = self.storyboard?.instantiateViewController(withIdentifier: "indentfier") as? CustomViewController{
    navController.pushViewController(viewController, animated: true)
}

In One line of code :

Swift 3:

self.navigationController!.pushViewController(self.storyboar‌​d!.instantiateViewCo‌​ntroller(withIdentif‌​ier: "view2") as UIViewController, animated: true)

self.navigationController!.pushViewController(self.storyboard!.instantiateViewControllerWithIdentifier("view2") as UIViewController, animated: true)
查看更多
Emotional °昔
3楼-- · 2019-03-10 23:28

APPDELEGATE TO PAGE:

        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let loginPageView = mainStoryboard.instantiateViewControllerWithIdentifier("leadBidderPagerID") as! LeadBidderPage
        var rootViewController = self.window!.rootViewController as! UINavigationController
        rootViewController.pushViewController(loginPageView, animated: true)

PAGE TO PAGE:

        let loginPageView = self.storyboard?.instantiateViewControllerWithIdentifier("scoutPageID") as! ScoutPage
        self.navigationController?.pushViewController(loginPageView, animated: true)
查看更多
狗以群分
4楼-- · 2019-03-10 23:31

Updated for swift 3/4. The most voted "one line of code" doesn't work because there's no navigation controller in "self"

let rootViewController = self.window!.rootViewController as! 
UINavigationController
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let profileViewController = mainStoryboard.instantiateViewController(withIdentifier: "ProfileViewController") as! ProfileViewController
rootViewController.pushViewController(profileViewController, animated: true)
查看更多
对你真心纯属浪费
5楼-- · 2019-03-10 23:39
func pushNewView() {
    if let wind = UIApplication.sharedApplication().delegate?.window {
        if let rootViewController = wind?.rootViewController {
            let viewToPush = YourViewController()
            let nav1 = UINavigationController(rootViewController: viewToPush)
            if let alreadySomeOneThere = rootViewController.presentedViewController {
                alreadySomeOneThere.presentViewController(nav1, animated: true, completion: nil)
            }else {
                rootViewController.presentViewController(nav1, animated: true, completion: nil)
            }
        }
    }
}
查看更多
女痞
6楼-- · 2019-03-10 23:41

Swift 3 & 4 best practices to push viewcontroller from AppDelegate:

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

   if let viewcontroller = storyboard.instantiateViewController(withIdentifier: "DiscussionBoardSID") as? DiscussionBoardViewController {
      viewcontroller.postID = "13" ///pass data to your viewcontroller
      rootViewController.pushViewController(viewcontroller, animated: true)
   }
}
查看更多
干净又极端
7楼-- · 2019-03-10 23:45

It seems that rootViewController actually is of type UINavigationController in my case, so casting it on declaration allowed me to call pushToViewController directly on it.

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String, annotation: AnyObject?) -> Bool {
    let rootViewController = self.window!.rootViewController as! UINavigationController
    let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let profileViewController = mainStoryboard.instantiateViewController(withIdentifier: "InstructionVC") as! InstructionVC
    rootViewController.pushViewController(profileViewController, animated: true)
    return true

}
查看更多
登录 后发表回答