web-dev-qa-db-ja.com

Swift-appDelegateのpushViewController、rootViewController.navigationControllerはnilです

いくつかのガイド、特に http://blog.originate.com/blog/2014/04/22/deeplinking-in-ios/ に従って問題が発生している

私はURLスキームを設定していますが、別のアプリからアプリを起動することはうまく機能していますが、ホストまたはURLを渡すことは期待どおりに機能していません。すべてのビューレイアウトにストーリーボードとインターフェイスビルダーを使用しています。

このガイドはappDelegateでこのopenURLを示しています。

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

ここに私のバージョンが簡略化されており、Swift=他のいくつかのソースから、つまり SwiftのAppDelegateからViewControllerのインスタンスを取得 問題の潜在的な他の変数を削除する瞬間。

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

}

Swiftバージョンはクラッシュを引き起こします:fatal error: unexpectedly found nil while unwrapping an Optional value

RootViewControllerにはnavigationControllerがまだないようです。

22
tehfailsafe

私の場合、rootViewControllerは実際にはUINavigationController型であるようですので、宣言にキャストすると、pushToViewControllerを直接呼び出すことができます。

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:条件付きバインディングとチェーンを使用してプッシュする安全な方法

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

1行のコードで:

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

ページへの出席者:

        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)

ページからページへ:

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

AppDelegateからViewControllerをプッシュするためのSwift 3および4のベストプラクティス:

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

Swift 3/4用に更新されました。 「自己」にはナビゲーションコントローラーがないため、最も投票された「1行のコード」は機能しません。

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