将 Tab Bar Controller 嵌入 Navigation Controller 时的 prepareForSegue
prepareForSegue when embedding Tab Bar Controller into Navigation Controller
我目前有一个这样的导航控制器设置:
和我的 prepareForSegue,它在初始视图(登录视图控制器)和导航控制器之间传递数据,如下所示:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
super.prepareForSegue(segue, sender: sender)
let navVc = segue.destinationViewController as! UINavigationController // 1
let chatVc = navVc.viewControllers.first as! ChatViewController // 2
chatVc.senderId = userID // 3
chatVc.senderDisplayName = "" // 4
}
但是,当我尝试像这样嵌入标签栏控制器(向我的应用添加更多 pages/functionality)时...
...和 运行 我的应用程序,我的程序在 let navVc = segue.destinationViewController as! UINavigationController
行崩溃
我知道问题是在我最初查看之后,它转到类型为 UITabBarController
而不是 UINavigationController
的选项卡栏,但是如果我更改它,我的数据不会转到我希望它去的视图...有点令人困惑。
如果您对如何实现此功能有任何想法,请告诉我,或者如果您有任何疑问,请随时向我询问。
谢谢!
P.s。我在控制台中收到的错误是:
Could not cast value of type 'UITabBarController' (0x10b8e48b0) to 'UINavigationController' (0x10b8e4860).
试试这个:
首先将 destinationViewController
转换为 UITabBarController
,然后使用 viewControllers
属性 访问 tabBarController 中的第一个 viewController:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let tabVc = segue.destinationViewController as! UITabBarController
let navVc = tabVc.viewControllers!.first as! UINavigationController
let chatVc = navVc.viewControllers.first as! ChatViewController
chatVc.senderId = userID
chatVc.senderDisplayName = ""
}
一个干净的方法是在您登录后立即使用类似的东西:
let controller = self.storyboard?.instantiateViewControllerWithIdentifier("setthisisyourstoryboard") as! UITabBarController // This would instantiate the TabBarController.
let navInstance = controller[0] as! UINavigationController // This would instantiate the navigationController, that is placed at 0th index in the array of all view controllers that are child to TabBarController, since you only have one child, you can use 0 as index
if navInstance.viewControllers[0] is YourClassName { // YouClassName is the name of the class right next to the navigation view controller, and it is also the only child of navigation Controller(0 index)
// You can also send some data here (for example the sender id)
(navInstance.viewControllers[0] as! YourClassName).someProperty = Value
}
// This line would present the tabBar controller, that would ultimately reach the end of the stack. I have used this approach in many apps, it works great!
self.presentViewController(controller, animated: true, completion: nil)
您可以在这之后删除 segue 并为 tabbarcontroller 设置 storyboard id。
我喜欢这样做,因为这样更自然。我的意思是 UITabBarController 主要是 View Controller 的父级,我不喜欢将 UITabBarController 设置为 UIView Controller 的子级的想法。
也许没什么不妥,但我不喜欢。
在 CS193p class 中,Paul Hegarty 展示了使用 extension
s 来处理导航控制器转场(第 8 讲:23')。 UIViewController
扩展引入了一个新的计算 属性: contentViewController
可用于所有 UIViewControllers(和 subclasses)。
我在下面发布的代码也适用于 TabBarViewControllers。
当您尝试将导航控制器转换为 ChatViewController 时,segue.destinationController.contentViewController 将递归地 return ChatViewController。
class LoginViewController: UIViewController {
/* ... */
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let chatVc = segue.destinationViewController.contentViewController as? ChatViewController {
chatVc.senderId = userID
chatVc.senderDisplayName = ""
}
}
}
extension UIViewController {
var contentViewController: UIViewController {
if let navcon = self as? UINavigationController {
return navcon.visibleViewController ?? self
} else if let tabcon = self as? UITabBarController {
return tabcon.selectedViewController ?? self
} else {
return self
}
}
}
这里。它对我来说工作得很好:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let tabVC = segue.destination as? UITabBarController {
if let navVC = tabVC.viewControllers!.first as? UINavigationController {
if let nextVC = navVC.viewControllers.first as? NextVC {
nextVC.varName = "works like a charm"
}
}
}
}
下一个VC 是您要将变量发送到的目标 VC。
我目前有一个这样的导航控制器设置:
和我的 prepareForSegue,它在初始视图(登录视图控制器)和导航控制器之间传递数据,如下所示:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
super.prepareForSegue(segue, sender: sender)
let navVc = segue.destinationViewController as! UINavigationController // 1
let chatVc = navVc.viewControllers.first as! ChatViewController // 2
chatVc.senderId = userID // 3
chatVc.senderDisplayName = "" // 4
}
但是,当我尝试像这样嵌入标签栏控制器(向我的应用添加更多 pages/functionality)时...
...和 运行 我的应用程序,我的程序在 let navVc = segue.destinationViewController as! UINavigationController
我知道问题是在我最初查看之后,它转到类型为 UITabBarController
而不是 UINavigationController
的选项卡栏,但是如果我更改它,我的数据不会转到我希望它去的视图...有点令人困惑。
如果您对如何实现此功能有任何想法,请告诉我,或者如果您有任何疑问,请随时向我询问。
谢谢!
P.s。我在控制台中收到的错误是:
Could not cast value of type 'UITabBarController' (0x10b8e48b0) to 'UINavigationController' (0x10b8e4860).
试试这个:
首先将 destinationViewController
转换为 UITabBarController
,然后使用 viewControllers
属性 访问 tabBarController 中的第一个 viewController:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let tabVc = segue.destinationViewController as! UITabBarController
let navVc = tabVc.viewControllers!.first as! UINavigationController
let chatVc = navVc.viewControllers.first as! ChatViewController
chatVc.senderId = userID
chatVc.senderDisplayName = ""
}
一个干净的方法是在您登录后立即使用类似的东西:
let controller = self.storyboard?.instantiateViewControllerWithIdentifier("setthisisyourstoryboard") as! UITabBarController // This would instantiate the TabBarController.
let navInstance = controller[0] as! UINavigationController // This would instantiate the navigationController, that is placed at 0th index in the array of all view controllers that are child to TabBarController, since you only have one child, you can use 0 as index
if navInstance.viewControllers[0] is YourClassName { // YouClassName is the name of the class right next to the navigation view controller, and it is also the only child of navigation Controller(0 index)
// You can also send some data here (for example the sender id)
(navInstance.viewControllers[0] as! YourClassName).someProperty = Value
}
// This line would present the tabBar controller, that would ultimately reach the end of the stack. I have used this approach in many apps, it works great!
self.presentViewController(controller, animated: true, completion: nil)
您可以在这之后删除 segue 并为 tabbarcontroller 设置 storyboard id。
我喜欢这样做,因为这样更自然。我的意思是 UITabBarController 主要是 View Controller 的父级,我不喜欢将 UITabBarController 设置为 UIView Controller 的子级的想法。
也许没什么不妥,但我不喜欢。
在 CS193p class 中,Paul Hegarty 展示了使用 extension
s 来处理导航控制器转场(第 8 讲:23')。 UIViewController
扩展引入了一个新的计算 属性: contentViewController
可用于所有 UIViewControllers(和 subclasses)。
我在下面发布的代码也适用于 TabBarViewControllers。
当您尝试将导航控制器转换为 ChatViewController 时,segue.destinationController.contentViewController 将递归地 return ChatViewController。
class LoginViewController: UIViewController {
/* ... */
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let chatVc = segue.destinationViewController.contentViewController as? ChatViewController {
chatVc.senderId = userID
chatVc.senderDisplayName = ""
}
}
}
extension UIViewController {
var contentViewController: UIViewController {
if let navcon = self as? UINavigationController {
return navcon.visibleViewController ?? self
} else if let tabcon = self as? UITabBarController {
return tabcon.selectedViewController ?? self
} else {
return self
}
}
}
这里。它对我来说工作得很好:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let tabVC = segue.destination as? UITabBarController {
if let navVC = tabVC.viewControllers!.first as? UINavigationController {
if let nextVC = navVC.viewControllers.first as? NextVC {
nextVC.varName = "works like a charm"
}
}
}
}
下一个VC 是您要将变量发送到的目标 VC。