What I need to do is basically build a container(view controller) that can change its child view controller dynamically and also set it's initial view controller dynamically.
I never used the Embed segue before so I thought I'll give it a shot.
However, using it seems to allow me to change the child view controller dynamically using a custom segue between the children view controllers but the initial view controllers seem to be fixed to the one I dragged the segue to in the StoryBoard(The custom segue here would be something alone these lines).
I know I can achieve what i'm looking for by creating x custom segue (where x is the number of children VCs I need) from the container view controller directly to the children and just calling these segues in code based on my needs.
But if that's the only way, what's the reason for using the "Embed" segue, is it only for really simple scenario's ?
An embed segue is not just for really simple scenarii. It can get pretty complicated. A major purpose is to cleanly separate code related to different concerns, that may still coexist on the same screen, into different view controllers. For instance, you could have an authentication controller and a preferences controller, both embedded into a single profile controller.
Related
I have a ProductDescription ViewController that gets called from a ProductTable UITableView that I have placed in many ViewControllers.
It doesn't seem very efficient to ctrl+drag a segue for each tableView in the Storyboard, as I have approx 20 of them.
How does one do this programmatically?
You have several options within UIKit to programmatically show a view controller without using a segue:
Push a view controller onto the navigation stack:
pushViewController:animated:
showViewController:sender:
Present a view controller modally:
presentViewController:animated:completion:
The real answer here is to use storyboard references. You shouldn't have the same thing in twenty different spots all trying to link to the same view controller to the point of asking this question.
So, let's create Product.storyboard, a storyboard which simply has two view controllers:
ProductTableViewController
ProductDescriptionViewController
And the appropriate segue between the two controllers.
Now, everywhere else in any of your other storyboards that want to use these controllers with this relationship, simply add a storyboard reference, add a container view controller, and add an embed segue between the container view and the appropriate view controller in the product storyboard.
You can accomplish this same effect even without using storyboard references. Ultimately, the main point is to use container views and make embed segues from everywhere you need this relationship to the first of these two controllers, and then there's just a single relationship created between the two product view controllers.
So suppose you need some functionality that requires next storyboard. For example you need to upload different content to view depending on what tab is clicked.
But the problem comes out when you try to use this storyboard. When you switch tabs you getting this behaviour.
But in first tab everything fine. So looks like it doesn't load view second time. Can somebody explain or give a link to the behaviour of navigation controller in this case, because I can't find anything useful in reference. Or how should I correct this behaviour in IB or programatically? Thanks.
a simple work-around is to put a "fake-viewcontroller" as root for the second navigation. On this "fake" controller execute in viewDidLoad a [self performSegueWithIdentifier: #"goToTheControllerHereWeGo" sender: self];
So, as I mentioned in my comment I do think this is a bug but we'll see how Apple responds. But yeah, segues have no love for view controllers that are the root view controllers of multiple navigation controllers. There are a number of workarounds depending on the context under which it comes up.
Best workaround : Share the navigation controllers, not their root view controllers
So for the simple example given above you could do this and everything would be fine:
Other workaround : This one is more applicable to complex storyboards that may have different custom navigation controllers so that sharing the nav controller isn't possible. One hilarious aspect of this issue is that when a view controller has two parent nav controllers in the storyboard, you won't know until runtime which one gets it! And further, on different runs they can switch :P (another reason I think this is a bug).
Sooooo from within prepareForSegue you can check if your navigation controller got unpacked with a rootViewController and, if it didn't, force it in there yourself:
UINavigationController* nc = segue.destinationViewController ;
if (nc.viewControllers.count == 0) {
nc.viewControllers = #[[self.storyboard instantiateViewControllerWithIdentifier:#"MyDetailVC"]];
}
Just provide more explanation beside the comments 'You cannot make a UIViewController as the root view controller of two different Navigation controller'. Suppose you can do so, then the view of the controller will be child view of the two navigation controller's view. It cannot happen as "it" cannot be a child of A but simultaneously a child of B.
On what condition will the tabview items switch , also trigger one of the two separate view controllers? what is the logic? when is it implemented? and no matter whatever the logic maybe, why does a single view controller (let us assume it is being filled up with different data according to the root) has 2 separate roots? we cannot add anything separately from the navigation controller itself,
Navigation controller is the flow that sets the storyboard in motion, but putting a VC as a subview of two different NC just has no point.
Think it of like this,
No additional information is provided by the Navigation controller itself, it just sets things in motion. So why would you want to put a VC as the child of 2root NC.
More easily think it as multiple inheritance, in objc, java its not possible because of the
Diamond problem. look it up and i hope it helps u understand
I'm currently building a custom view controller container for my iOS project and I nearly understand what I'm doing. The one thing I'm stuck on is how do you (properly - aka not a hack) add a view controller in PART of the Parent controller's frame. See how there are multiple view controllers/views in the email app? How does one build a custom controller container that designates the location of such sub-view controllers? How do you properly add such a controller? I'd like to know the "correct" way as designated by apple (best practice).
EDIT: After looking at this some more I was thinking a possible way would be to create views with custom sizing and then push those to the parent. Is this the correct way?
You sort of answered it yourself. The view you have as an example uses a UISplitViewController to show two separate views (left and right). Each of those views has a view controller that owns it. Note that the left side includes all of the view, like the search, nav bar, and toolbar. So just create two separate view controllers and add them to a UISplitViewController and you should be golden! The views themselves are created however you normally create views. Storyboards, NIBs, or in code works.
I am trying to create a class that is similar in functionality to the UITabBarController, but with some fundamentally different functionality. It is called a dropdownViewController and has a primary content view with a UITabBar-like interface at the top of the screen that allows for other UIViewControllers to be modally presented and dismissed over this primary viewController.
I would like this class to be able to be set up using the storyboard to some extent, and I have created a custom Segue that connects my dropDownViewController class with each of its child viewControllers.
My current solution is to assign identifiers to each of the Segues that are then stored in array within the dropdownViewController. I can call the segues programmatically using the performSegueWithIdentifer: method, but this solution isn't as flexible or intuitive as I would like to to be.
Right now, all the custom Segues that I have setup are connected to the "manual" triggered segue in the storyboard connections panel for the dropdownViewController. (I would put screenshots but this is my first post)
However, I want to mimic the functionality of the UITabBarController class, which has an alternate triggered segue in the storyboard connections panel called viewControllers that each of its child views are assigned to. Unless there are some compile-time macros handling these story board interactions, I assume that the UITabBarController uses these connections to determine what it's view controllers are. However, I can't figure out how to setup this functionality with my own class
After searching around for a solution, it seems likely that this is functionality Apple kept for its own use and is limited to their own classes as a feature in Xcode, but if anyone has solutions or ideas it would be greatly appreciated.
I haven't tried this, but I think you should be able to do it with your own custom segues. In the perform method, you would just add the destination view controller to the source view controller's (DropDownViewController) array of view controllers. In the DropDownViewController's viewDidLoad method (or maybe in an initializer or awakeFromNib, not sure which is most appropriate), you would execute all these segues so that they run right after the controller is loaded like is done for a tab bar controller.
When using custom container view controller, I don't quite understand why the presenting view controller needs to specify the from, because being the container class, it should already know what's in the view hierarchy, no?
transitionFromViewController:toViewController:duration:options:animations:completion:
Container view controllers sometimes need to put the views of the contained controllers into specific subviews of their own view. (For example, a SplitViewController reimplementation might have left and right positioning views holding the master and detail controller views respectively.) Providing the fromViewController tells UIViewController where in the view hierarchy the new controller's view should be inserted, and also which specific view should be removed after the animation.
(contrary to another answer, the frames of the views aren't set for you at all. You do that, before the call, and in the animation block. The "Creating Custom Container View Controllers" system guide in the docs has a pretty good example.)
As it happens, actually using transitionFromViewController:... appears to be optional. You can manage your view hierarchy manually, with or without animations, and it works fine. I'm still forming my opinions, but I think I prefer to do it manually, to more easily handle cases where one of the VCs is nil.
This is done this way to allow you to have a view controller that has views with viewControllers in it. The from defines the originating view controller and gives the system the ability to position the animations appropriately.
Imaging you had a view with 4 views in it like tiles. the main view controller can consecutively call this on its "child" view controllers and with the from -> to specification, it won't make the assumption that the caller is the from viewController.