At my storyboard I have a part where a view controller with a table view is placed before a tab bar controller. This tab bar has two view controllers. Earlier I used the table view already, and when I clicked on one cell I passed to another Viewcontroller which loaded another view controller with table and cells with the id from the pushed cell from the first table. Like this:
The tableview controller, prepare for segue:
if segue.identifier == "overviewSegue" {
var caseViewController: CaseViewController = segue.destinationViewController as CaseViewController
var caseIndex = overviewTableView!.indexPathForSelectedRow()!.row
var selectedCase = self.cases[caseIndex]
caseViewController.caseitem = selectedCase
}
This works well. Now I want to do the same, but the only difference is that the last view controller is part of a tabbar controller. The problem is I can't get it working to pass the data to this last table view controller.
I tried several things, but I can't point the data to the tabbar table view. Segue's are not approachable, and the destination isn't the table view controller, but the tabbar controller, etc. The question, how to pass data from a tableview through the tabbar controller to another view controller.
I have found a solution:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "toTabController" {
var tabBarC : UITabBarController = segue.destinationViewController as UITabBarController
var desView: CaseViewController = tabBarC.viewControllers?.first as CaseViewController
var caseIndex = overviewTableView!.indexPathForSelectedRow()!.row
var selectedCase = self.cases[caseIndex]
desView.caseitem = selectedCase
}
}
Easy explanation: You need to get to your Tab bar controller and pick his view controllers. It normally has two, so you can pick the first. After that, define which class it belongs to, and you can pass your data just as you did before.
Related
I want to pass data from a view controller to tabbar controller, and then from this tab bar controller to its view controller with using their class. I succeeded to transfer from view controller to tabbar controller using segue. However, I cannot transfer data from tabbar controller to its one of the view controller.
Any idea/documentation will be appreciated. Here is the screenshot about what I want to do from xcode
screenshot-xcode
Take a look at the documentation for the tab bar controller, in particular the viewControllers property.
That property is an array of UIViewControllers, in the order they appear in the tab bar, so you can pick the one you need (viewControllers[0] from your screen shot), cast it to your specific view controller subclass and then pass it your data.
At last, I am able to solve the issue, many thanks to the answer. Here is the detailed explanation for beginners like me:
This is the source controller class, which is a tabbar controller and it transfers the data:
class SourceTC: UITabBarController {
var dataTransferFrom = "transfer this string"
override func viewDidLoad() {
super.viewDidLoad()
let finalVC = self.viewControllers![0] as! DestinationVC //first view controller in the tabbar
finalVC.dataTransferTo = dataTransferFrom
}
}
and this is the destination controller class, which is a view controller under tabbar controller and it gets the transferred data:
class DestinationVC: UIViewController {
var dataTransferTo = ""
override func viewDidLoad() {
super.viewDidLoad()
print(dataTransferTo)
}
}
I have a Main VC which has a connection to Tab Bar Controller via segue and that Tab Bar controller has 2 sections and those are 2 ViewControllers. I need to pass data from Main VC to that specific VC which derived from Tab Bar Controller using segue. Since i am able to use only one segue (to show only TBController), is there any way to achieve to pass data directly from main to another by skipping Tab Bar controller?
Ps. Those 2 VC have a navigation controller connection between Tab Bar Controller and themselves as well.
Try This
var secondTab = self.tabBarController?.viewControllers[1] as SecondViewController
secondTab.array = firstArray
On prepare for segue function you can get the tabBar associated controllers via TabBarControllers property viewControllers - that let you select one of a tab bar controller's view controllers to become the active view controller. then you use tabBarController's property selectedIndex to actually segue to that VC.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let index = 0//the index of the tab you wish to segue to
if let bar = segue.destination as? TabBarVC {
if let nav = bar.viewControllers[index] as? UINavigationController {
if let navChildVC = navigationController.viewControllers[0] as? YourVCType { // index of the controller of enumerate to find it
// pass data to navChildVC
bar.selectedIndex = index
}
}
}
}
I promise that I'm completely new to Xcode and Swift, so I know I am making silly mistakes but I don't know where. This is part of my iOS app storyboard:
where the segue between the first table view and the second navigation controller is called myTaskDetailSegue and its type is Show (e.g. Push). Now I have some problems:
Neither in the first table view controller nor in the second the back button is showed and I don't know why. Many people told me that navigation bar and back button are as default in navigation controllers but they did not appear
In the class of the first table view controller here is the method prepareForSegue()
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "myTaskDetailSegue" ) {
let indexPath = self.tableView.indexPathForSelectedRow()
let task = self.taskCollection[indexPath!.row] as Task
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailsMyTasksViewController
controller.detailItem = task
println("segue mostra task \(task.id)")
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
so you can read that the segue identifier is correct but when a row is tapped nothing happens and the second table view controller is not showed.
I don't really know what I am missing because of my inexperience.
Here is the complete storyboard:
You don't need two UINavigationController's to what you want to achieve. Is important to note that every time you push(with a segue or manually) a new UIViewController it's added to the navigation stack.
According to Apple:
Pushing a view controller displays its view in the navigation interface and updates the navigation controls accordingly. You typically push a view controller in response to user actions in the current view controller—for example, in response to the user tapping a row in a table.
So you can remove the second UINavigationController in your Storyboard and make the segue directly to your DetailsMyTaskViewController and update your prepareForSegue like in the following way:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "myTaskDetailSegue" ) {
let indexPath = self.tableView.indexPathForSelectedRow()
let task = self.taskCollection[indexPath!.row] as Task
let controller = segue.destinationViewController as! DetailsMyTasksViewController
controller.detailItem = task
println("segue mostra task \(task.id)")
}
}
And your back button should appear by default as you said before. Nevertheless I strongly recommend you read the following two guides :
UINavigationViewController
View Controller Programming Guide for iOS
For a better understanding of the navigation stack, etc.
I hope this help you.
I just ported my project over to Swift 2, and everything is working great - except that even the most simple segues have no back button. Here is the prepare for segue function that I am using:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if segue.identifier == "showExercise" {
if let nav = segue.destinationViewController as? UINavigationController {
if let exercisesController = nav.topViewController as? ExercisesController {
let cell = sender as! WorkoutCell
if let workout = cell.name!.text {
exercisesController.exercises = Workouts[workout]!
exercisesController.navigationItem.title = workout
}
}
}
}
}
Before, the back button to the parent segue used to automatically populate. Now, all I get is the title in the child navigation vc
Are you using show or show detail segue? It seems like you are using a modal segue. Destination view controller for show or show segue is usually the second view controller itself, and not embedded in another UINavigationController.
If your destination view controller for the show segue is really a UINavigationController, the new navigation controller's navigation bar settings may override the old one (the navigation controller of the source view controller). Try not embedding your destination view controller in another UINavigationController.
I have a set of view controllers linked to a tab controller.
When a image is selected on one of these tabbed views a segue is executed and a detail viewocntroller not linked to the tab controlled is opened.
Pronblem is when I navigate back to the tabbed view controller via segue from the detail view, the tabs are no longer visible.
Before segue executed on tabbed vc:
Same vc with no tab after segue from vc not linked to tab controller
Question is how to ensure tab will be visible on vc when called via the non tabbed vc?
Just to add the tabbed view connected to tab controller is a collection view, the detail view segue is excited when user sects an image:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
println(segue.identifier)
println(sender)
println("SEGUE SELECTED: \(segue.identifier)");
if(segue.identifier == "segueToDetailScrollView"){
// pass the cell
let cell = sender as CollectionViewCell;
let indexPath = collectionView?.indexPathForCell(cell);
let vc = segue.destinationViewController as ScrollView;
var image = arrayOfIUmages[indexPath!.row];
var imageTitle = titles[indexPath!.row];
println("Image to segue name : \(image) and the title : \(imageTitle)");
println("The vew controller \(vc)");
vc.currImage = UIImage(named: arrayOfIUmages[indexPath!.row]);
vc.textHeading = self.titles[indexPath!.row];
}
}
You will need to create a segue to the tabcontroller and let tab controllers set the inner view. Onload you can check for a shared default or something similar to find which tab should be shown.
Need to use unwind method in target view controller to allow navigation back to the same instance navigated from, good example here http://www.raywenderlich.com/81880/storyboards-tutorial-swift-part-2