ios Swift - 来自 appDelegate 的 pushViewController,rootViewController.navigationController 为零
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25256353/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Swift - pushViewController from appDelegate, rootViewController.navigationController is nil
提问by tehfailsafe
Having a problem following a few guides, specifically http://blog.originate.com/blog/2014/04/22/deeplinking-in-ios/
遵循一些指南时遇到问题,特别是 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.
我正在设置 url 方案,从另一个应用程序启动应用程序运行良好,但传入主机或 url 并没有像它应该的那样工作。我正在为所有视图布局使用故事板和界面构建器。
The guide shows this openURL in appDelegate:
该指南在 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;
}
}
Here is my version simplified and in swift from a few other sources, ie Get Instance Of ViewController From AppDelegate In SwiftI'm skipping the conditional for the url host at the moment to remove potential other variables in the problem.
这是我从其他一些来源简化和快速的版本,即 在 Swift 中从 AppDelegate 获取 ViewController 实例我正在跳过 url 主机的条件,以删除问题中潜在的其他变量。
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
swift 版本导致崩溃:
fatal error: unexpectedly found nil while unwrapping an Optional value
It seems that rootViewController doesn't have a navigationController yet?
似乎 rootViewController 还没有 navigationController ?
回答by tehfailsafe
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.
在我的情况下,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
}
回答by Kumar KL
SWIFT 4:Safe way to push with the use of conditional binding and Chaining
SWIFT 4:使用条件绑定和链接的安全推送方式
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:
斯威夫特 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)
回答by A.G
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)
回答by Jeremy
Updated for swift 3/4. The most voted "one line of code" doesn't work because there's no navigation controller in "self"
更新为 swift 3/4。投票最多的“一行代码”不起作用,因为“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)
回答by Doci
Swift 3 & 4 best practices to push viewcontroller from AppDelegate:
从 AppDelegate 推送视图控制器的 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)
}
}
回答by José Raúl Toledano R
If you want to present and dismiss with NavigationBar or Dismiss(Animated: true, completion: nil) Set addObserverin didFinishLaunchingWithOptions
如果您想使用 NavigationBar 或 Dismiss(Animated: true, completion: nil) 显示和关闭,请在didFinishLaunchingWithOptions 中设置addObserver
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
NotificationCenter.default.addObserver(self, selector: #selector(devolucionNoPresencial), name: NSNotification.Name(rawValue: "DevolucionNoPresencial"), object: nil)
return true
}
then in your method
然后在你的方法中
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
//do your code for .active, .inactive .background, etc
if let userInfo = response.notification.request.content.userInfo as? [String : AnyObject] {
if UIApplication.shared.applicationState == .active {
//activate the notificationCenter so you can call your @objc method
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "DevolucionNoPresencial"), object: nil)
}
add @objc method
添加@objc 方法
@objc private func devolucionNoPresencial() {
//change DevolucionVC for VC you want to present
if let controller = DevolucionVC() as? DevolucionVC {
if let window = self.window, let rootViewController = window.rootViewController {
var currentController = rootViewController
while let presentedController = currentController.presentedViewController {
currentController = presentedController
}
currentController.present(controller, animated: true, completion: nil)
}
}
}
}
回答by Anilkumar
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)
}
}
}
}