web-dev-qa-db-fra.com

Swift - pushViewController de appDelegate, rootViewController.navigationController est nul

Avoir un problème en suivant quelques guides, en particulier http://blog.originate.com/blog/2014/04/22/deeplinking-in-ios/

Je configure le schéma d'URL et cela fonctionne bien pour lancer l'application à partir d'une autre application, mais la transmission de l'hôte ou de l'URL ne fonctionne pas comme il semble. J'utilise des storyboards et un constructeur d'interface pour toutes les dispositions de vue.

Le guide montre cette openURL dans 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;
    }
}

Voici ma version simplifiée et en Swift à partir de quelques autres sources, c'est-à-dire Get Instance Of ViewController From AppDelegate In Swift Je saute le conditionnel pour l'hôte URL à le moment de supprimer d'autres variables potentielles dans le problème.

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

}

La version Swift provoque un crash: fatal error: unexpectedly found nil while unwrapping an Optional value

Il semble que rootViewController ne dispose pas encore de navigationController?

22
tehfailsafe

Il semble que rootViewController soit en fait de type UINavigationController dans mon cas, donc le convertir en déclaration m'a permis d'appeler pushToViewController directement dessus.

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

}
25
tehfailsafe

Swift 4: Un moyen sûr de pousser avec l'utilisation de la liaison conditionnelle et du chaînage

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

Dans une ligne de 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)
26
Kumar KL

APPÉLÉGER À LA 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 À PAGE:

        let loginPageView = self.storyboard?.instantiateViewControllerWithIdentifier("scoutPageID") as! ScoutPage
        self.navigationController?.pushViewController(loginPageView, animated: true)
8
A.G

Meilleures pratiques Swift 3 et 4 pour pousser le Viewcontroller depuis 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)
   }
}
2
Doca

Mis à jour pour Swift 3/4. La "ligne de code" la plus votée ne fonctionne pas car il n'y a pas de contrôleur de navigation dans "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)
2
Jeremy