Im pretty new to ios development and am starting with a viewcontroller that displays a table of data. When I click on one of the cells, I try to push a tabbarcontroller into view. It works, but I can't see the tabs and the view area is black instead of displaying either of the two default views associated with the tabbarcontroller.
If I set the tabbarcontroller as the intialviewcontroller, it works fine, but this breaks my design.
Any help appreciated.
UDPATE: this is how I'm pusing the tabbarcontroller into view
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let vc = TrialSiteViewController()
navigationController?.pushViewController(vc, animated: true)
}
I tried about four different ways to transition from my tableviewcontroller to my tabbarcontroller and the only way I could get this to work was to use a segue setup in my storyboard with an identifier, then call this when I click the cell.
performSegueWithIdentifier("trialSitesSegue", sender: self)
Probably obvious to a lot of IOS developers, but I am new to all this, so still thought I would share.
Related
I’m making an application on UITableView and I want to make a function, when I click on a cell, I open another view controller, on which there will be a back button, I want that when I click on this button, the newly opened controller closes, and returns me to that the controller from which it was opened, how to do it?
This code is for creating a new controller when clicking on a cell (without the function to open the controller, because I don’t know yet with which method I can implement this)
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = createVC(rootVC: AboutRecipeViewController(), TBImageName: nil, TBTitle: recipes[indexPath.row].recipeName)
}
The new ViewController got a method for that.
dismiss(animated: true, completion: nil)
Create an IBAction for your Back Button and run this method when the button got pressed. That should dismiss the new ViewController and get you back to the initial one.
However, your syntax with the back button seems to be similar to a UINavigationViewController. Consider using this makes it way more easy.
I currently have a ViewController with prototype cells in a UITable View. The cells currently display content from a Firebase DB when loaded. What I would like to do is when a cell is pressed more information is shown from the Firebase DB. However, I currently cannot get the segue to push to the ViewController from the cell. What should I do so this would work?
Image of my Storyboard--
These are two pieces of code that will help. For swift:
#IBAction func showEntries(_ sender: Any) {
self.performSegue(withIdentifier: <sequeId>, sender: nil)
}
and a button with the action wrapping this.
For Objective C, you can perform the segue like so.
[self performSegueWithIdentifier:#"showEditor" sender:self];
Create the action by CTRL and dragging the button or cell into the corresponding code file, select action and name it.
It's hard to tell, but from the screenshot, it looks like the segue goes from controller to controller, rather than cell to controller. If you'd like to do it like this, then you need to give the segue an identifier (in the right panel of your screenshot) and then override the delegate method
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "yourIdentifier", sender: self)
}
OR (if you don't feel like going to all this trouble)...in the storyboard, drag the segue from the cell to the view controller you want to push, rather than from controller to controller.
For example,
Notice how when the segue is selected, only the cell is outlined in blue, rather than the entire view controller.
It's because cells are dynamic, so you can't assign an event handler from cell to uiviewcontroller. Instead you should make the segue inside your cellForRowAtIndexPath method and push it from there. If you want to see the segue inside the storyboard nevertheless, then you can also ctrl+drag from viewcontroller1 to viewcontroller2 to make a new segue. Then select the segue and give it a Storyboard id. After That you can call self.performSegue(withIdentifier: "yourIdentifier")
I actually found the solution to this. The issue was fairly simple actually. All I had to so was change the selection setting within the table view attributes from 'No Selection' to 'Single Selection'.
I want to create the following user flow in my Swift application:
User clicks a button
A modal view pops over with a choice. The user selects a choice.
A second view appears with another choice (using a "show" transition, so the user can press < Back to alter choice #1). The user selects the second choice.
The second modal view segues back to the original view (which has the button).
To do this, I created the following structure:
--> NC1 --> VC1 --modal-> NC2 --> VC2 --show-> VC3 (NC = UINavigationController,
^ | VC = UIViewController)
| |
----Segue I'm trying to achieve-----
I've tried to pop all the way back to VC1 by passing a reference to VC1 all the way through to VC3, then calling the following code in VC3:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Perform Segue
print("Trying to segue")
rootController!.navigationController!.popToRootViewControllerAnimated(true)
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
where rootController is the reference to VC1. Unfortunately the segue doesn't occur; the second modal view stays on the screen, but I get the "Trying to segue" message printed.
Am I trying to implement this user flow the right way? If so, any suggestions why I can't pop to a root view in another navigation controller?
If you are using storyboards, you can do this using an unwind segue.
In VC1 implement an #IBAction method, which takes a UIStoryboardSegue as parameter:
#IBAction func unwindToVC1(sender: UIStoryboardSegue) {
}
Then from the Prototype cell of VC3 control-drag to the Exit icon of the view controller, select Selection Segue: unwindToVC1: and you are good to go.
You can achieve a similar result using code also.
Implement didSelectRowAtIndexPath in VC3 like this:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
navigationController!.dismissViewControllerAnimated(true, completion: nil)
}
First sorry for my english.
I have a UISplitViewController and i replaced the template master UITableViewController with an UIViewController put a UITableView and UIContainerView what contains a second static UITAbleViewController for settings one of this settings cell has another detail UITableViewController to change its value. on iPhone works well but on iPad with that splitviewcontroller this settings value table shows over on the splitviewcontroller detail view. its good too but i can't hide anymore. (On iPhone has a back button and just works well)
I couldn't find the solution.
My question is how can i hide that detail view to show the original detail view of the split view?
Here are my 3 pics from storyboard, the initial view and when the settings values are opens(that can't be hide n iPad)
Any advice would be nice. Thanks
Storyboard
Ipad screenshots
Finally i made an easy solution. Delete show detail storyboard segue on settings tableviewcontroller and define didSelectRowAtIndexPath for custom push
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//i want only the third row to perform an action
if indexPath.row == 2 {
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let groupListViewController = mainStoryboard.instantiateViewControllerWithIdentifier("GroupListViewController") as! GroupListViewController
self.navigationController!.pushViewController(groupListViewController, animated: true)
}
}
This way i can push any view to the split view left or right side cos both have navigation controller. After this i defined the same function on the pushed tableviewcontroller fire some action and go back. It works like a charm on iPad and iPhone too.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.appDelegate.client.selectedGroupIndex = indexPath.row
//The main master viewcontroller of split view
let vehicleListViewController = self.navigationController?.viewControllers.first as! VehicleListViewController
//settingsviewcontroller that embedded in master viewcontroller
let vehicleListSettingsViewController = vehicleListViewController.childViewControllers.first as! VehicleListSettingsViewController
//call a custom function on embedded settings viewcontroller to change selected value
vehicleListSettingsViewController.changeGroup(indexPath.row)
//refresh splitviewcontroller's master tableview
vehicleListViewController.tableView.reloadData()
//Easy go back to masterview
self.navigationController?.popViewControllerAnimated(true)
}
I'm learning about iOS as I write an application that uses a UITableViewController and Core Data to display a list of items, and another view controller that also uses Core Data to configure a variety of additional attributes that are not shown in the table view.
A button in the UITableViewController's navigation bar segues to another view that lets me set a variety of details. This is done using a storyboard "Show Detail" segue, and it works fine.
I want to use the accessory action button in a UITableViewCell to segue to the same detail view controller, so I created another "Show Detail" segue in the storyboard that connects the accessory detail button to the detail view controller (ie: the same kind of segue as the button in the navigation bar)
Confusingly, when I click the detail accessory button at run time, nothing happens, and prepareForSegue is never called.
The UITableView cell style is Subtitle, and I've configured it to have a Detail accessory action. However, the accessory button isn't displayed unless I specifically add it:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: Storyboard.reuseID)
let tone = toneTable[indexPath.row]
cell.textLabel!.text = tone.valueForKey("toneName") as? String
cell.detailTextLabel!.text = tone.valueForKey("toneDescription") as? String
cell.accessoryType = UITableViewCellAccessoryType.DetailButton
return cell
I finally gave up, and called prepareForSeque myself:
override func tableView(tableView: UITableView, accessoryButtonTappedForRowWithIndexPath indexPath: NSIndexPath) {
let tone = toneTable[indexPath.row]
self.performSegueWithIdentifier("ShowToneDetail", sender: tone)
}
(I'm using the sender parameter as a convenient place to pass an NSManagedOject)
Now, prepareForSegue gets called, but if I put a breakpoint in prepareForSegue, I see that segue.destinationViewController points to the the source view controller, not the destination view controller. This is unfortunate, because I'd like to pass some values to the new instance of the destinationViewController.
Interestingly, the segue does correctly instantiate the destinationViewController, and passes control to it.
But, I don't understand what's going on. I don't know why I have to call prepareForSeque myself, and I don't know why the segue's destinationViewController isn't set correctly.
What am I doing wrong?
ps: is it just my perception, or is XCode less mature than other IDEs like Eclipse?
You're creating your cells in the wrong way. You should be using dequeueReusableCellWithIdentifier:forIndexPath: to dequeue a cell using the identifier you setup in the storyboard. By doing it the way you are, you're directly instantiating a cell that "knows" nothing about the cell in the storyboard where you added the detail disclosure button, or the segue you made.
I have no idea why the segue.destinationViewController would point to the source view controller. My guess is that it doesn't, and maybe you have your controller classes mixed up.