Storyboard screenshot with description
I've used this line of code in the UIViewController class of 2nd tab to access the tabBarViewController. But it crashes.
let friendView = self.tabBarController?.viewControllers![2] as! AccountTableViewController
Note: AccountTableViewController is the name of UITableViewController class of 3rd tab.
Thanks for your help.
Change your code like this
let navController = self.tabBarController?.viewControllers![2] as! UINavigationController
for vc in (self.navigationController?.viewControllers)! {
if (vc.isKindOfClass(AccountTableViewController.classForCoder())) {
let friendView = vc as! AccountTableViewController
}
}
Related
In have a UITabBarController with several UIViewControllers. Inside one of the controllers, when a certain condition is met, I want to instantiate another UIViewController which is a child of the same UITabBarController.
I keep getting this error "Application tried to present modally an active controller", but I don't understand how is scheduleNavController already active. I looked up several answers on SO, but I still don't understand what is my mistake and how can I solve it?
The flow of the app is like this: WelcomeViewController,LoginViewController,UITabBarController and the children of the UITabBarController.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabController = storyboard.instantiateViewController(withIdentifier: "CentralTabBarControllerID") as! UITabBarController
if let viewControllers = tabBarController?.viewControllers {
let scheduleNavController = viewControllers[1] as! UINavigationController
let scheduleVC = scheduleNavController.childViewControllers[0] as! Schedule
tabController.present(scheduleNavController, animated: true, completion: {
scheduleVC.segmentedControlIndexReceivedFromClaimDetail = self.segmentedControlIndex
})
}
Thanks to Andreas Oetjen suggestion to use the selectedIndex of the UITabBarController I have come up with another solution. However, I still don't know exactly how I should fix my code from the original question to make it work.
//select index of the UIViewController we want to switch to
// get the UINavigationController for the tab we want to switch to
// get UIViewController to which we want to pass data
self.tabBarController?.selectedIndex = 1
let scheduleNavController = tabBarController?.viewControllers?[1] as! UINavigationController
let scheduleVC = scheduleNavController.childViewControllers[0] as! Schedule
scheduleVC.segmentedControlIndexReceivedFromClaimDetail = self.segmentedControlIndex
//remove the the current UIViewController from which we switch to another controller above.
let claimDetailNav = tabBarController?.viewControllers?[0] as! UINavigationController
let claimDetailVC = claimDetailNav.childViewControllers[1] as! ClaimDetail
claimDetailVC.removeFromParentViewController()
I have implemented a tabViewController with some pages. one of those page is a tableview controller. after clicking on tableview item i am opening another viewController. Now i want to go back to that specific page. the selectedIndex of that tab Page is 1.
How can i do this?
Thanks for your help
store board
Try this
let tabBar: UITabBarController = self.window?.rootViewController as! UITabBarController
tabBar.selectedIndex = 1
If you are outside from tabBar Controller.
self.tabBarController?.selectedIndex = 1
If you are already in tabBar Controller and move to another tabBar Controller. Go to the ViewDid of TabBar method and paste the code.
override func viewDidLoad() {
super.viewDidLoad()
self.selectedIndex = 1
}
If you want the user to be able to go back to tableViewController after clicking on a cell you should use a navigationController instead.
You are using UITabBarController as rootViewController then can do this:
if let appDelegate = UIApplication.shared.delegate as? AppDelegate{
if let rootTabBarController = appDelegate.window?.rootViewController as? UITabBarController{
rootTabBarController.selectedIndex = 1
}
}
im guessing there needs to be changes in the app delegate? Thanks for the help!
1) Create a sample Master/Detail via xcode
2) Drag a TabBarController on the storyboard
3) Change the TabBarController to the initial view controller.
4) Control Drag from the TabBarController to the SplitViewController
5) Assign a title to the SplitViewController in the storyboard
6) In the app delegate replace the reference to the SplitViewController as follows.
let tabBarViewController = self.window!.rootViewController as! UITabBarController
print(tabBarViewController.viewControllers?.count)
var splitViewController:UISplitViewController? = nil
for viewController in tabBarViewController.viewControllers! {
if viewController.title == "Master" {
splitViewController = viewController as? UISplitViewController
}
}
let navigationController = splitViewController!.viewControllers[splitViewController!.viewControllers.count-1] as! UINavigationController
navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController!.displayModeButtonItem()
splitViewController!.delegate = self
I have quite a complicated setup in my app that involves an embedded UISplitViewController which feeds a bunch of UIViewControllers.
What I am needing to do is pass an NSManagedObject through the embedded UISplitViewController so I can access it in my separate detail' UIViewControllers.
I have attached an image of my storyboard with some awesome annotations....
This is my prepareForSegue function at the minute, this is in the View Controller where I already have my NSManagedObject, I am looking to pass it to the first SurveyViewController so it can get passed on:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
println("Sender is \(sender)")
if segue.identifier == SurveyIdentifier {
// let nav : UINavigationController = segue.destinationViewController as! UINavigationController
// let itemVC: BACUploaderViewController = nav.topViewController as! BACUploaderViewController
let surveyViewController: SurveyViewController = segue.destinationViewController as! SurveyViewController
println("survey view controller: \(surveyViewController)")
// if let destination = segue.destinationViewController as? MasterViewController {
//
// destination.workItem = sender as? Work
// }
}
}
I am fairly sure that I have to access my MasterViewController from here by drilling down through the View Hierarchy, but not sure on how to achieve this effectively?
On a side note, the segue does work, I am presented with the correct views, but it pushes the view onto the screen twice and I'm not sure why, I can upload a gif of this if seeing what I am talking about in action might make more sense?
You can "reach down" through the hierarchy of view controllers, to get a reference to the table view controller titled "Sections" in the storyboard.
From prepareForSegue in your SurveyViewController:
// the destination of the "embed" segue will be the split view controller
let splitVC : UISplitViewController = segue.destinationViewController as! UISplitViewController
// in a UISplitViewController, viewControllers[0] represents the Master view controller
// in your case that is a UINavigationController...
let navVC: UINavigationController = splitVC.viewControllers[0] as! UINavigationController
// In a UINavigationController, topViewController represents the visible VC
// In your case that's the Sections table view controller...
let sectionsVC : SectionsViewController = navVC.topViewController as! SectionsViewController
// (replace "SectionsViewController" with the correct class name)
sectionsVC.object = yourNSManagedObject
This passes the object to the Sections view controller. You can pass the object to the final VCs (the bad boys!) in the prepareForSegue of the Sections view controller. You can't do it earlier, because they are not instantiated before then.
As to why the view might be pushed onto screen twice, my only guess is that you might be using performSegueWithIdentifier from within didSelectRowAtIndexPath of a table view, when the segue is also linked directly to the prototype cell.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
println("Sender is \(sender)")
if segue.identifier == SurveyIdentifier {
// let nav : UINavigationController = segue.destinationViewController as! UINavigationController
// let itemVC: BACUploaderViewController = nav.topViewController as! BACUploaderViewController
let surveyViewController: SurveyViewController = segue.destinationViewController as! SurveyViewController
***********************
surveyViewController.managedObject = self.managedObjectContext
************************
// if let destination = segue.destinationViewController as? MasterViewController {
//
// destination.workItem = sender as? Work
// }
}
}
You can have an optional named managedObject in your SurveyViewController and then inject your managedObjectContext object from MasterViewController to SurveyViewController. This code snippet is written keeping in mind that you are in MasterViewController
I am trying to Compile my app again now that Swift 2 is out and the thing is I am having an error with TabBarController instances.
I am declaring the instances in vars in order to use methods from anothers ViewControllers.
Here it's my code:
let barViewControllers = self.tabBarController?.viewControllers
let listViewController = barViewControllers![2].viewControllers![0] as! dbViewController //The [2] is because it's the third TabBar and the [0] it's because It's embebed in a NavigationController.
let calendarViewController = barViewControllers![1] as! CalendarViewController
In the second line Im having the following error:
UIViewController does not have a member named "viewControllers"
Anybody could help me?
Thanks
You are trying to access the property viewControllers of the type UIViewController, which it doesn't have. viewControllers is a property on a UITabBarController, but viewControllers returns an array of UIViewController.
Cast viewControllers to an array of UITabBarController (or only the item you extract) to access it's viewController property.
Like this:
let barViewControllers = self.tabBarController?.viewControllers as! [UITabBarController]
Or this:
let listViewController = (barViewControllers![2] as! UITabBarController).viewControllers![0] as! dbViewController