Show(e.g. Push) from a viewcontroller to a navigation controller works?! Why? - ios

So I am new to IOS programming and I am using the Swift language.
After doing a couple of beginner apps. I have had some trouble on figuring the difference between the Show(e.g. Push) and the deprecated Push segues.
What I want to do is to Show/Push from a ViewController A(embeded with Navigation Controller B ) to a Navigation Controller C (containing a View Controller D).
Since when I disable the "Use size classes", the Push segue doesn't work and will report error "pushing to a navigation controller is not supported". This error makes sense since you can only push regular view controllers.
However when I enable the "Use size classes" (which turns the Viewcontroller to a square instead of a rectangle), I was able to Show(e.g. Push) to a navigation controller, which really confuses me.
So what's the main difference between the Show(e.g. Push) and the deprecated Push? As to my knowledge there is no major functional difference but the fact seems to prove me wrong and makes me confused..

Update:
I have recreated the behavior you observe. The Show (e.g Push) segue does indeed work from one viewController embedded in a navigationController to a second viewController embedded in a different navigationController.
Note that when the push happens, the second viewController slides in in the normal push way, and a back button appears that takes you back to the first viewController. This tells you that the second viewController is actually being pushed onto the stack of the first navigationController. So instead of giving you the error message, it is simply ignoring your second navigationController.
When using a navigationController, only the first viewController is imbedded in a navigationController. You don't have to embed subsequent viewControllers in a navigationController, because when you wire up the Push segue from a previous viewController in the navigationController's stack, the Storyboard will recognize that this new viewController is controlled by a navigationController and it will add the navigationBar at the top.
Original Answer:
A Show (e.g. Push) segue is an Adaptive Segue. It chooses the correct segue type based upon the situation.
If your source viewController is in embedded in a Navigation Controller, it does a Push.
If your source viewController is in a SplitViewController without a NavigationController, it does a Replace.
In all other cases, it does a Modal segue.
So, it works because it is actually doing a Modal segue in your case, which works if you aren't using size classes. You will notice that the presented viewController actually slides in from the bottom which is a tell-tale sign of a Modal segue.
You can find information about it here:
Backward Compatibility of Active Segues.

Related

UINavigationController vs viewController embed in NavigationController

I was trying my hands on iOS and while building apps, one question get into mind that what is the difference between UINavigationController vs viewController embed in NavigationController.
While using UINavigationController we push and pop views.
while using viewController we present and dismiss.
SO what are the applications where one is more superior to use than the other.
UINavigationController is used where you want you move back and forth in your application. Generally Navigation controller is used when you are navigating in more detailed information in each level of depth you are in your application.
UIViewController is generally preferred when you display polished information. in UINavigationController generally it is the one of the last controller you push in your controller
I think you are really describing two sides to the same coin. There is only one way to use a UINavigationViewContorller. It is a known as a container view controller and its job is to push and pop other UIViewControllers. A UINavigationViewController works with viewControllers, not views.
UINavigationController:
If you have hierarchy of view controller then that is you have stack of view then you need to use navigation controller. You can perfrom push and pop operations on the view controller and Navigation Controller is the rootViewController of all ViewController.so to go back to the previous one, in a ordered way. Imagine that controllers in a navigation controller will just build a sequence from left to right.
UIViewController: if you are using view controller it act as presentViewController. The presentViewController offers a mechanism to display a so-called modal view controller; i.e., a view controller that will take full control of your UI by being superimposed on top of a presenting controller. I think that presentViewController is most suitable for use with just one view controller being presented at a time. So you simply will not be able to implement a "go back"/navigation like functionality.
UINavigationController inherits from UIViewController. The strange thing about this object model is the UIViewController has a property called NavigationController. So for OO purists this is a bit baffling that a parent class knows about its children. But moaning aside this is how it’s been done in UIKit. As you’ll find with a runtime error, you can’t place a UINavigationController inside a UINavigationController
Whenever you push a controller, it can access the parent UINavigationController it may or may not belong to via the NavigationController property. The property is null if the controller is not inside a UINavigationController.

'Show' segue in Xcode 6 presents the viewcontroller as a modal in iOS 7

I have two view controllers in my iPhone application (built with swift) built with Xcode 6.1 and uses storyboards.
The first view controller is embedded in a navigation controller in the storyboard and the segue for the second view controller is a 'Show' segue.
When the application is run, it properly shows the transition as a push in iOS 8.x, but in iOS 7.x it appears as a modal without the navigation bar.
My application requirement is to show the transition as a push regardless of whether it's iOS 7 or iOS 8. Any ideas to get this working as push in both versions of the iOS?
I saw a related post where this issue is mentioned, but could not find a solution to the problem: Adaptive segue in storyboard Xcode 6. Is push deprecated?
Any help is appreciated...
Thanks
This solution is different from the others in the following ways:
It includes a method to examine and verify the issue
The cause of the issue is traced to the source (a change in the segue type)
The solution is very simple (delete and recreate a new segue)
Please note the requirements in the text
I just gave a very detailed SO answer that fully explains what is happening and why, but the simple solution is you can delete the Segue that is not pushing and then recreate it on the storyboard. The reason is that there is likely a broken bit of xml in the segue (see extended answer for example/instructions how to confirm this issue).
After you confirm that you have at least one UINavigationController within the view hierarchy, be sure that the segue is NOT a manual segue and does NOT have an action associated with it (by viewing the segue in the storyboard as Source Code). Delete the existing segue and then Ctrl-drag from a UIView/UIControl to the target view controller and if custom action is needed intercept the call to destination controller in prepareForSegue.
Also to confirm that this solution works for you please do the
following:
Verify that your initial view controller (with the arrow on it) is a
UINavigationController and that it has a normal content view
controller as it's root view controller. (or that you embed your
initial view controller inside of a UINavigationController)
Read my extended comments on an earlier response to a very similar question (linked above).
It's possible that you have assigned the Initial View Controller to your UIViewController instead of the UINavigationController. Also, select your UIViewController and check that the "Is Initial View Controller" option is unchecked.
Here is the workaround for that. It looks like a bug in Xcode for iOS 7. You need to create a dummy UINavigationController and link all your free UIViewControllers to this navigation controller. Worked for me.
For me, my storyboard lacked a navigation controller. I am creating the navigation controller programmatically, which works fine in iOS8, but not iOS7.
SOLUTION
In your storyboard, select the main view controller and in the Xcode menu, choose Editor > Embed In > Navigation Controller.
Select the new navigation controller, and in the attributes inspector on the right, under View Controller, make sure Is Initial View Controller is checked.
Run the app. Should be fixed now.
I believe this is a bug in Xcode 7.2. In order to workaround, you can create a "Push (deprecated)" segue and then in the Storyboard editor, select the segue and change it to Show(e.g. Push)
I have had this exact issue with "Show (eg. Push)" for ages and I have just figured it out whilst trying to push a view controller onto a navigation controller that is in a Popover. It seems that the context of the called View Controller is the problem. So this is how I resolved it:
On the View Controller performing the Segue, check the "Defines Context" property in the Storyboard.
In the called View Controller, set the Presentation property to "Current Context".
I ran into this problem and the only solution I found that works for me is to use the deprecated 'Push' segue.
I am using XCode 9 with Swift 4. Note this version came out yesterday (September 20th).
For me this was just a caching bug. I had to choose "Present Modally", run the app and then choose "Show (e.g. Push)". Now everything works fine.
Basically the answer of Jomafer is partly correct. The controller which you are pushing needs to be preceded by a UINavigationController. You dont really need to push the UINavigationController at all. As long the storyboard knows its within a UINavigationController, all is well.
When a "Show" segue comes up as a modal segue in testing it is usually one of two problems:
The first view controller is not inside a navigation controller.
The storyboard XML is corrupted.
The solution to #2 is usually to remove and replace the segue, and it should correct itself. Sometimes just switching to some other presentation style, running, and switching back to "Show" fixes it.
This can also happen to "Show Detail" segues, and it can be more insidious.
Example:
I have a series of view controllers arranged in a UISplitViewController. They have segues Show->Show->Show->Show Detail. The last segue kept coming up modal. I tried everything to fix that last segue. The problem was that the upstream Show segue had been corrupted into a Show Detail segue (even though the storyboard still said it was a Show segue). I had been testing on iPhone, and I did not discover the real problem until I ran it on the iPad simulator. The segues were now Show->Show->Show Detail->Show Detail. On the iPhone the third segue looked just like a Show because it collapsed onto the navigation controller. However, it is still the detail view controller, and you cannot have a Show Detail from a detail view controller, so the OS does what it can to get your view controller on screen and displays it modally.
Lesson 1: Always test your UISplitViewController on iPad to make sure the segues are doing what you think.
Lesson 2: If your segue is coming up modal unexpectedly, check the upstream segues for corruption as well as the segue in question.
Problem in my case was that I created Show (e.g. Push) segue before putting ViewController as rootViewController of UINavigationController. In other words I didn't have UINavigationController.
Then I deleted seque, added UINavigationController and added seque again and it worked. Tested on Xcode 9.0.1 / iOS 11.0.3.

What is Replace Segue in iOS?

I know how to do it but i need to know the details, internals. How is it different from modal segue?
replace segue from code
The differences is push segue needs a UINavigationController in order to perform.
A modal segue is not in a navigation stack they can only dismiss themseleves you do not pop view back to the previous controller like you do with a push segue.
A replace segue is only relevant on iPad or iPhone 6+. You can use replace segue to replace the contents of the master or detail pane of a UISplitViewController.

Switching UINavigationViewController to UITabBarController with Segues

I am changing my app to use UITabBarController instead of UINavigationViewController. I replaced controllers accordingly and app launches with tabs successfully. Later in the code I came across some difficulties using segues where lines like
[self performSegueWithIdentifier:#"ImageViewController" sender:self];
won't work producing error
"Push segues can only be used when the source controller is managed by an instance of UINavigationController"
When I embedded UINavigationController into the initial FirstViewController, line above worked fine. I need that line to switch between views and pass some data to another view controller.
The problem is that using segue identifier to go to SecondViewController hides TabBar navigation (unless I wrap SecondViewController in UINavigationController again and so on). That is not the solution.
Question: How to use UITabBarController and still take advantage of segues while keeping tab navigation visible?
"Push segues can only be used when the source controller is managed by an instance of UINavigationController"
Sounds to me like you are using a push segue somewhere outside a navigation controller. Try to select all "segue bubbles" in interface builder that are not inside a navigation controller:
and check the segue's style in the right pane:
If the style is set to the value push as shown above change it to modal or custom:
There is something wrong with your connections. If you are using interface builder (storyboard) then your connections should look like this. See pic
Notice you are missing UINavigation Title headers. Also the gray area below on each view controller means that space is reserved for images for UITabBarController
Another problem is your UIToolBar. Looks like its sitting on top of where UITabBar will be displayed. That may/may not get your app rejected by apple since you already have a UINavigationController and UITabBarController. If you need more buttons/options on that page make them UIButtons instead.

ViewController to NavigationController and back

I have one problem for which im not sure how to solve. Currently i have main UIViewController with some buttons. This is the initial view that is created with app. On it, one button calls storyboards segue with style Modal on ViewController which is part of UINavigationController. After that few other viewcontrollers are handled within the UINavigationController via segues and getting back via navigationController:popViewControllerAnimated. What i dont know is how to get back from UINavigationController to first UIViewController. I tried, when I'm on first one on navigationctrl,
[self removeFromParentViewController];
yet that only removes the view but it seems that UINavigationController somehow stays alive as result is black screen. Creating unconnected segue and call it from code would be possibility, but im not sure if that is the proper way. Would that leave navigation controller alive ?
Is there any reason you are using a UIViewController first and THEN a UINavigationController?
Why not change this so that the UINavigationController is the initial view controller and then drive everything from there.
If you want the first view to not have a nav bar then you can hide it easily.
That way you can move around through all views by popping and pushing through the UINavigationController.

Resources