Table View Cell Action Between View Controllers - ios

I have an app that is two view controllers connected via a tab bar controller. The first view is a tableView cell and the second is several labels that are connected.
Currently my code works so that when I select a cell in the table view, it brings up the associated information from the second view controller. However, to get back to the first view controller, I currently have a back button.
How do I make it so the tab bar controller buttons don't disappear when the cell is tapped, so that I can quickly and more seamlessly jump between the two view controllers?
Relevant code for selecting a cell:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
x = indexPath.row
y = indexPath.row
z = indexPath.row
performSegue(withIdentifier: "seque", sender: self)
}
And then I call this in the viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
xLabel.text = wordList[x]
yLabel.text = wordDefinition[y]
zLabel.text = wordSnippet[z]

If I understand this correctly, you need to have your first VC embedded into a NavigationController and the Navigation Controller embedded into a TabBarController.
This way, when you drag a segue from your first VC to your second VC, the second VC will also be embedded into the same Navigation Controller.
And since the Navigation Controller is inside a TabBar Controller, the second VC will also be embedded into the same TabBar Controller.
You will end up with something like this:
As you can see, all VCs retain the TabBar and the Navigation Bar.
And you can do this by selecting the desired VC and then from Editor menu > Embed in.

Related

In UISplitViewController, how to make master open detail view controller for iPhone?

I have a bit of a unique UISplitViewController setup (I think). My master view controller is a table view controller within a navigation controller, which is normal. However, my detail view controller is a UITabBarController. Each tab has a navigation controller to wrap the content within.
When the user selects a table row within the master view controller, I select a tab in the detail view controller and start pushing a view controller:
let detailViewController = masterViewController?.splitViewController
.viewControllers[1] as? UITabBarController
let selectIndex = 2
let viewController = (detailViewController.viewControllers?[selectIndex] as? UINavigationController)?.viewControllers.first
detailViewController.selectIndex = selectIndex
viewController.show(myCustomViewController)
This works great on iPad.. selecting an item in the master view controller table selects the tab in the detail view controller and pushes view controllers to it.
On iPhone, I have the master view controller shown on initial load using this post:
class MasterViewController: UIViewController {
private var collapseDetailViewController = true
override func viewDidLoad() {
super.viewDidLoad()
splitViewController?.delegate = self
}
// ...
}
extension MasterViewController: UISplitViewControllerDelegate {
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool {
return collapseDetailViewController
}
}
extension MasterViewController {
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
collapseDetailViewController = false
selectTabAndPush(index: 2, vc: myCustomViewController)
// Tried swapping the order of these but still no luck
}
}
However, selecting a row in the master view controller table literally does nothing. How can I get the detail view controller to show when a row in the master table is selected?
At very first, why you need both functionalities : Master-Detail and Tab. Because if you are implementing master detail with tab then you must have equal number of tab with the equal number of rows in Master, then only you can navigate to the tab when you select row. In iPhone there would be max 5 tabs only and if you have 7 rows in Master then what happened if user will click on row 6 and 7?
Because as per design concept : You should choose only one as per requirements.
Master-Detail -> Provides facilities like side menu, so user can access many more option from these.
TabBar -> Provide facilities of more option with having menu at bottom.
Anyway, you might have some unique requirement.
As you said on iPad it is working fine. So for iPhone you can go with below way :
UI in storyboard should be like :
Create or add UITabBarController in your project. (I have created tabbarcontroller named CustomTabController).
Then in didSelectRowAt, push tabbarcontroller :
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.phone {
let tabController = self.storyboard?.instantiateViewController(withIdentifier: "CustomTabController") as! CustomTabController
self.navigationController?.pushViewController(tabController, animated: true)
tab.selectedIndex = indexPath.row
}
else {
// iPad code here
}
}
But make sure, that you have enough number of tabs same as number of rows.

Swift: Back Button shows in Storyboard but not Simulator

Back Button shows in StoryBoard but not Simulator.
I added a segue from TableViewController to DetailViewController to pass data. The Storyboard automatically shows a Back Button on DetailViewController, but when I run the Simulator, the button doesn't show up.
This is my Storyboard:
A closer look of TableViewController and DetailViewController:
But in my Simulator the button doesn't show up:
The hierarchy of the whole project:
I want to know where to configure the back button(in my segue?), or instead deleting the button(not letting it show in the Storyboard) so I can create one myself.
The code of my segue in my TableViewController:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showDetailView", sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch (segue.destination, sender) {
case (let controller as DetailViewController, let indexPath as NSIndexPath):
controller.receivedName = storeList[indexPath.row].name!
controller.receivedDesc = storeList[indexPath.row].desc!
controller.receivedRate = storeList[indexPath.row].rate
controller.receivedUrl = storeList[indexPath.row].url!
default:
print("unknown segue")
break
}
}
Your initial view controller in the storyboard is actually the TabelViewController (you can see there is an arrow to it).
Thats' why when you start the scene and the TableViewController shows but it is not embedded in the navigation because the navigation controller has never been created.
Just change which is the initial view controller to be the navigation controller or any other before the navigation controller which holds the TableViewController.
You can just drag the arrow to change the initial controller in the storyboard

Segue of Table cell in a tab and navtigation view controller

I've just recently started learning about Xcode and the swift language. To get myself familiarise with them I'm trying to build a simple app with what I've learnt so far. 1
The screenshot shows what I want to achieve. VC1 and VC2 are both a navigation + tab VC. When the user taps on the "Preset" button on the navigation bar of VC1, the screen will switch to VC2 which has a table with different preset values. What I did was to create an action segue (show) from the "preset" button to VC2. All good so far.
This is what I want to do but couldn't figure a way to do it: At the table at VC2, when the user click on any row, he will be brought back to VC1 and the value in the selected row is being inserted into a textfield in VC1.
What I had tried to do was to create an action segue (show) from the table cell to VC1. But by doing so, the navigation bar and tab bar on VC1 and VC2 has disappeared 2
Is what I'm trying to do achievable? if yes, what did i do wrongly?
I tend to use storyboards with an IBAction to return to the previous view controller, such as
#IBAction func userDidSelectTableCell() {
self.navigationController?.popViewController(animated: true)
}
But in your case I think your after a unwind segue, I've not used one but you can read more about them at this following link https://spin.atomicobject.com/2014/10/25/ios-unwind-segues/.
Hope that helps
For your purpose you need to use a unwind segue. In order to achieve this, you firstly need to declare a global variable in your VC2 class which stores the value of the selected row. You can use the didSelectRow method for that.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedCell = indexPath.row
self.performSegue(withIdentifier: "YourIdentifier", sender: self)
}
you need to add a #IBAction method in you VC1 class.
#IBAction func unwindtoVC1(_ sender: UIStoryboardSegue){
if let sourceVC = sender.source as? YourTableViewController {
yourTextFiled.text = sourceVC.selectedCell
}
}
In you storyboard, in VC2, Control+drag-drop from viewController to Exit portion to create a segue.
From the pop-up that comes, select the unwindtoVC1 method.
Now, select the segue and in the attributes inspector, give it any identifier.
Use this identifier in your VC2 class, in the didSelectRow method, in the self.performSegue(withIdentifier: "YourIdentifier", sender: self)
Hope this helps.

Segue won't show the ViewController when pressed

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'.

How can hide on iPad an embedded secondary UITableViewController's DetailView on a UISplitViewController master using UIContainerView

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)
}

Resources