Swift, segue to split View Controller from Tab Bar Controller - ios

I would like to preface this by saying I am new to Swift and IOS development.
I currently am attempting to perform a segue from a tab bar view back to the root view controller which is a split view controller.
From the picture below I would like to select the 'cancel' button and return to my root view controller which is a split view controller
Below is the storyboard segue I set up
Below is the code I am using.
#IBAction func cancelButton(_ sender: Any) {
performSegue(withIdentifier: "submit", sender: nil)
}
When I initially launch my app and begin using it. Everything works correctly.
As shown below when an item is selected from the left side the correct data populates in the detail view.
Even the side push menu works correctly when first opened as seen below.
However, it is when I select the 'Submit Mail' option in the side menu and attempt to return to the rootview with a segue that the app starts to break down.
As shown below when I return with the segue I have set up the data no longer populates in the detail view when selecting an item from the master view.
Furthermore, the side push menu is now full screen when opened.
Any reason as to why this is happening?
As a further note I am using the Cocoapod SideMenu for the side push menu.
Thanks!

Segues are used to push controllers onto the navigation hierarchy, not to go backwards, as you are attempting to do. You should think of your navigation hierarchy as a tree structure, where there are rarely any cyclic relationships between controllers. You add and remove controllers from the hierarchy to go 'forwards' and 'backwards'. What actually happens in your scenario is that a new instance of your root controller is getting pushed onto the navigation stack, one that has not been initialised with the state that your original root controller had. Although it is possible to use a special kind of segue called unwind segues to go 'backwards', I would not recommend that, since they are complicated to wire, and make for code that is not explicit about what it does.
Instead you could use UIViewController.dismiss in combination with the delegate pattern to achieve what you want.

To return from the tabBarController, I would just set an unwind segue:
declare the unwind in the root view controller (no code needed in the func)
#IBAction func unwindToRootViewController(_ sender: UIStoryboardSegue) {
// You can print("I returned"), just to test
}
Connect the button that will trigger return to the exit button of tabBarController and select unwindToRootViewController

Related

Best segue after posting content

I am new to swift and I am curious about the best way to move from one view to another. I have a main view that is a tab on a tab bar and embedded in a navigation controller. From this main view, I am taking user content and then displaying that content on the main view. Currently I am segueing from the main view to a view that collects content and then another segue back to the main view. The only problem is that when I do this I get a back button and even if I hide the back button, I am just continuing to put screens on top of the tab. What would be the best way to transition from the view that collects content back to the main view?
Basically there're 2 general ways how view controllers are shown and hidden:
Push in the navigation controller (either with 'Show' segue or in code self.navigationController?.pushViewController(viewController, animated: true). In that case the normal way to return to previous screen would be to use 'Back' navigation button. If you need to do it manually you can use self.navigationController?.popViewController(animated: true) inside your view controller or use unwind segue (though I rarely see it used). If you need to come back to the very first screen in your navigation stack you can use self.navigationController?.popToRootViewController(animated: false).
Modal presentation (either with 'Present Modally' segue or with self.present(viewController, animated: false). In that case in order to return to the previous view you have to add some close/cancel button on your screen and bind it with the code which call self.dismiss(animated: true, completion: nil).
Anyway to have a full picture I'd recommend to get familiar with Apple guide on this subject.
And if you need to pass some data between your controllers, ther're various ways to do it, like assigning it directly to a property in prepare(for segue: UIStoryboardSegue, sender: Any?), implementing delegate/callback interactions, implementing observers, shared back storages, etc.

Unwind segue doesn't work

i'm doing an app that uses a TableViewController with a system of Adding/Editing items, using the same view. (however when you add an item the view is modal presented and when you edit it is shown)
I followed the great starter tutorial from Apple so basically my Storyboard looks like this
The segue going through the Navigation Controller is for adding and the other one is for editing. (I did everything according to the tutorial).
I did a segue between the Cancel item bar button and the exit icon of the ViewController and it works well when the view is modally presented (when I try to add an item).
However when I click on a cell to reach the view with the segue that shows it (to edit an item), both items in the navigation bar stop working. The prepareForSegue method is not called anymore. So I can't cancel or save.
I tried creating an unwind segue between the ViewController itself and the exit icon and to call it programmatically like this:
#IBAction func testButton(sender: UIBarButtonItem) {
print("we're inside")
self.performSegueWithIdentifier("cancelSegue", sender: self)
print("so what now")
}
and when I try to edit it and tapping the cancel button it results by just showing the two log messages and kind of skipping the performSegueWithIdentifier method. However adding still works fine.
Am I doing something wrong or have I misunderstood some basic notion about unwind segues?
This seems like quite a strange solution to your problem. While I can't comment on specifically why your unwind segue isn't working in the second case, things will start to get quite complicated with dismissing the New Programsegue since you're displaying it two different ways.
The common approach that we use is:
Use two completely different view controllers for creating and updating an assets. May be some duplicate code, but makes it slightly easier for other people to work on.
Use the same view controller for creating and updating buttons. If you're editing an item, you can pass it to the view controller with prepareForSegue. When the view controller loads, if an item is present, you can change the behaviour of the buttons, title etc. If no item is present, you know to create a new item.
For most implementations, it's much simpler to dismiss the views programatically. (i.e [self dismissViewControllerAnimated:NO completion:nil] for modal views and [self.navigationController popViewControllerAnimated:YES] for just returning to a vc in the same navigation controller stack.
Update
Did you link the Cancel button to the exit icon on the first view controller, or the second view controller (the one with the cancel and save button)?

Why is the tab bar disappearing?

My current setup of viewcontrollers are:
tab view > navigation controller > table view controller > navigation view controller > cell details. Please see
The current setup of viewcontrollers
I used to have:
tab view > navigation controller > table view controller > cell details
and then everything was fine.
The issue is that I need a custom action to happen when the user presses the back button, and to do this i added a nav controller between the "table view" and the "cell details". And thats when the tab bar disappeared. I understand this seems to be "normal" behaviour, but that don´t help me much. Please help.
The code that segues to the detail view controller. (I use the storyboard, so light on code for these things)
#IBAction func add(sender: AnyObject) {
dispatch_async(dispatch_get_main_queue()) {
self.performSegueWithIdentifier("TableViewToDetailView", sender: self)
}
It happens when hideTabBarOnPush property is true(in code) or Hide Bottom Bar on Push is checked on storyboard for the controller you are pushing.
I had a similar problem and the right question was kind of hard to ask. using Tsb Bar Controllers with Navigation Controllers and View Controllers os too tricky and certain things a re not allowed and there is a lot of terminology, and, there are many different types of segues,and there are many different kinds of consequences for doing certain things.
I found the correct procedure (answer) in the second part of this two part series:
Storyboards Tutorial for iOS: Part 1
Storyboards Tutorial for iOS: Part 2
Summary of the procedure:
Embed the source and destination View Controllers in Navigation Controllers, then create unwind segues (methods with the signature#IBAction func methodname(_ segue:)) in the source view controller. Then, from the destination View Controller, control-click from the navigation bar button (or any view required to trigger a return to the first view controller) to the Exit object above the view controller then pick the correct action name from the popup menu. The unwind segue will be accessible from the Document Outline and can be given an identifier to use in prepare(for:sender:) in case data needs to be sent to the from the destination view controller. Also, the segue from the first view Controller to the second navigation controller must be modal.
A similar issue I met although maybe not quite the same as yours but hope it may help. When view controller A presents view controller B, the hidesBottomBarWhenPushed property of B could be overridden by the hidesBottomBarWhenPushed property of A. I fixed it by setting B's modal style.

Transition from UIViewController to TabBarViewController

I have been searching for a solution for 6 hours, and come up with nothing that applies to my situation. my storyboard follows the flow of:
TabBarViewController -> NavigationController ->TableViewController -> UIViewController (see picture below)
When the "Notify" button, in the last view controller (Stranger view controller), is clicked, I want to programmatically transition/segue from that View Controller(Stranger View Controller), to a different child of the TabBarViewController (it is the controller titled "Look Around" within the illustration).
Every time I perform a traditional segue:
option + drag segue from Stranger View Controller --> Look Around
View controller
Give segue an identifier
programmatically use self.performSegueWithIdentifier.
I get a transition. but the "Look Around" tab bar is gone in the storyboard, and in the simulator, once I hit "Notify", the view changes to the "look around" view, but the tab bar below does not reflect that change, as it still has the previous tab highlighted.
I have already handled all the other processing within the IBAction function that I need to handle. It is just a matter of, correctly, sending the user to a different view, once they have hit "Notify".
Any guidance on this would be greatly appreciated.
If you have any questions or concerns for me, please do not hesitate to ask. I am new at this, and am open to any help.
ViewController is a child of NavigationBar and NavigationBarController is a Child of TabBarController. So Segue is not required as it will disturb the flow.
Try programmatically
#IBAction func notifyButtonTapped(sender: AnyObject) {
tabBarController?.selectedIndex = 1
tabBarController?.tabBar.hidden = false
self.navigationController?.popToRootViewControllerAnimated(false)
}

How to Give Button Exit Functionality in iOS

I am designing two pages, one followed by the other, in Xcode 7. Let's call them the first and second view controllers. From a button in the first view controller, with a modal segue, the second view controller shows up. I want to add a button to second view controller so that when I hit that button, I can simply exit from the second and back to the first view controller.
I know this feature can be done by navigation controller with putting cancel button to the navigation bar on second view controller which I don't want to. I want specifically a button to have that functionality.
I thought of calling the first view controller with code when the button is tapped, but it sounds me like a bad coding. So, I would like to learn what is a good way of achieving this.
Thanks,
Add method to the second view controller:
#IBAction func exitButtonPressed(sender: AnyObject) {
dismissViewControllerAnimated(true, completion: nil);
}
Next add button to the second view controller in interface builder and connect button's action to this method.
use Unwind Segues
Unwind Segues give you a way to “unwind” the navigation stack and specify a destination to go back to.
for sample tutorial1, tutorial2

Resources