UITAbBarController as Master in UISplitController and showDetail: - ios

I have a storyboard with this situation;
The root view controller is a UISplitViewController with:
MASTER: a UITabBarController
0 ->UINavigationController -> ...other ViewControllers
1 ->UINavigationController -> ...other ViewControllers
DETAIL: a UINavigationController -> a DetailViewControler
With this hierarchy the segue showDetail from last viewcontroller in master to the Navigation Controller in Detail doesn't work because the Detail is presented Modally in a Collapsed environment instead of presenting it with a push.
I think this behavior comes from the Tab Bar Controller because it isn't a Container like a UINavigationController. In fact if i remove the tab bar and set a navigation as Master of Split View Controller it works like usual.
What can i do for using a tab bar like Master of Split View Controller and get the right behavior of showDetail segue in a collapsed environment?
P.S.: for right behavior i mean pushing the Detail in the Master Navigation Controller in a horizontal compact environment (iPhone 6 plus Portrait).

I solved this issue overriding these methods of the UISplitViewControllerDelegate and implementing inside them all the behavior i want from the SplitViewController:
primaryViewControllerForCollapsingSplitViewController
splitViewController:collapseSecondaryViewController:ontoPrimaryViewController
primaryViewControllerForExpandingSplitViewController
splitViewController:separateSecondaryViewControllerFromPrimaryViewController:
I suggest you to take a look at UISplitViewController Documentation because it explains very well the behavior of the Split Controller:
UISplitViewController Documentation
You can find what you need here:
The split view controller performs collapse and expand transitions when its size class toggles between horizontally regular and horizontally compact. During these transitions, the split view controller changes how it displays its child view controllers. When changing from horizontally regular to horizontally compact, the split view controller collapses one view controller onto the other. When changing from horizontally compact back to horizontally regular, it expands the interface again and displays one or both of its child view controllers depending on the display mode.
When transitioning to a collapsed interface, the split view controller works with its delegate to manage the transition. At the end of a collapse transition, the split view controller normally shows only the content from its primary view controller. You can change this behavior by implementing the primaryViewControllerForCollapsingSplitViewController: method in your split view controller delegate. You might use that method to specify the secondary view controller or an entirely different view controller—perhaps one better suited for display in a horizontally compact environment. If you want to perform any additional adjustments of the view controllers and view hierarchy, you can also implement the splitViewController:collapseSecondaryViewController:ontoPrimaryViewController: method in your delegate.
The expansion process reverses the collapsing process by asking the delegate to designate which view controller becomes the primary view controller and to give the delegate a chance to perform the transition itself. If you implement the delegate methods for collapsing your split view interface, you should also implement the primaryViewControllerForExpandingSplitViewController: and splitViewController:separateSecondaryViewControllerFromPrimaryViewController: methods for expanding that interface. If you do not implement any of the methods, the split view controller provides default behavior to handle the collapsing and expanding transitions.
For more information about the methods you use to manage the collapse and expand transitions, see UISplitViewControllerDelegate Protocol Reference.
Hope this can help you.
PS: sorry for bad english.

During a showDetail segue the Split View Controller checks if collapsed and calls showViewController on the primary, which in this case is the tab controller which doesn't implement this method so relies on the default view controller method which is to search up the hierachy to find on that does; in this case showViewController called on the Split View Controller which implements it by firs checking if collapsed then it calls presentViewController which is why you see it as presented modally.
To solve this you could subclass the Tab Controller, implement showViewController and call it on the selected view controller, which would be the current navigation controller.
You also need to handle the collapse and separate, one way would be to implement separateSecondaryViewControllerForSplitViewController in your tab subclass and forward that on to the nav controller child that contains the detail nav controller because that is what un-hides its nav bar and pops it off the stack. You wouldn't get that behaviour if you implemented the split controllers' separateSecondary delegate method

Related

Difference between navigation controller and viewcontroller?

Difference between navigation controller and viewcontroller?
I mean how can we decide when to use navigation controller or a normal view controller?
Just my two cents:
A UIViewController represents a single view and you can put buttons in this view controller to segue to another UIViewController. If you want to segue back to the first UIViewController, you will have to worry about putting a button in the second view controller that leads back to the first. If you are drilling down into view controllers, this can be tedious having to remember to give the user a way back to a previous view controller.
A UINavigationController does a lot of this tedious work for you. As mentioned, it contains a stack of UIViewControllers. It will create a navigation bar at the top that will allow you to easily go back up the hierarchy of view controllers.
In short, if you have a hierarchy of view controllers that you want the user to easily navigate around, inbed your UIViewControllers into a UINavigation controller.
UINavigation Controller is a combination of 2 or more view controllers,those are connected through "segue" feature of "Ios". Benefit of using Navigation Controller is that we can navigate between different screens easily with default "Back" button on each screen . We don't need to give any individual button to move back onto previous screen.
Whereas a ViewController provides a single screen & we can connect more screen using "segue" but we also have to design a "Back" button to navigate onto previous screen.
We should use Navigation Controller , in case where one option resides into another one.Like in an iPhone settings ->Mobile Data Options->Voice->4G or 3G or 2G. It's a hierarchy of menus so here navigation Controller is better option than using UIController.
We should use UiController with "segue " , in case where
we have to choose one option among multiple.Like -
Photos ->There are many folders in which , any one is selected, that are Favourites or People or Places .
Here's a very brief, high-level overview.
Whereas a UIViewController can be thought of as representing a single 'screen', UINavigationController, as the name implies, is used as a means of being able to navigate multiple 'screens'.
From the documentation:
The UINavigationController class implements a specialized view controller that manages the navigation of hierarchical content. This navigation interface makes it possible to present your data efficiently and makes it easier for the user to navigate that content. You generally use this class as-is but in iOS 6 and later you may subclass to customize the class behavior.
Please see the rest of the UINavigationController documentation here: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/index.html
Okay, Thank you everyone for helping me to find out a clear answer on this.
Navigation Controller consists of navigation bar and tool bar to move in and out from view controllers present in navigation stack.Therefore there can be many view controllers in Navigation Controller.
In view controller we don't have this facility and it represents a single screen view.
Please correct me If I am wrong.
See the Navigation Controller discussion in the View Controller Catalog.
Bottom line, a navigation controller actually is a view controller, but it just happens to be one that presents and navigates between other view controllers.

What is actually inside navigationController's "view" property?

I was going through Apple's documentation about navigation controller and find this point ambiguous and hard to comprehend.
It was written in this online documentation of navigation controller.
Navigation Controller Views
A navigation controller is a container view controller—that is, it
embeds the content of other view controllers inside of itself. You
access a navigation controller’s view from its view property. This
view incorporates the navigation bar, an optional toolbar, and the
content view corresponding to the topmost view controller. Figure 2
shows how these views are assembled to present the overall navigation
interface. (In this figure, the navigation interface is further
embedded inside a tab bar interface.) Although the content of the
navigation bar and toolbar views changes, the views themselves do not.
The only view that actually changes is the custom content view
provided by the topmost view controller on the navigation stack.
From that, my understanding is that inside this "view" property. There should be at least two subview inside this view.One is the navigationBar the other is the contentView of the current displayed viewController’s view. But while I am debugging only the navigation bar showed with another view called UINavigationTransitionView showed.
My question is, is this normal. Have I done anything wrong?
Second, what is the most common way to access current displayed viewController's view with only the reference to the navigation controller.
Thanks
UINavigationTransitionView controller contains one wrapper view which intern will have the current uiviewcontroller's view.
You can probably find this view as a subview of UINavigationTransitionView. However this is not the "right" way to do this. The proper way is to go through property "topViewController" and then take its view:
self.navigationController.topViewController.view
If there is another view controller or its view that you need, you have access to whole view controller's hierarchy across navigation controller through viewControllers property.
self.navigationController.viewControllers
More here:
https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UINavigationController_Class/index.html

Adding Popover to current Navigation Controller hierarchy

I've seen a lot of other questions on here about adding a UINavigationBar to a UIPopoverController. All of the examples I've seen follow one of two patterns:
In the init or viewDidLoad method of the Popover subclass, you alloc-init a UINavigationBar directly, as suggested here. This method is a little hacky, and while it shows up nicely, if the popover is a UITableViewController, you have to mess with a bunch of things to make sure the navigation bar you just added doesn't overlap one of your cells.
Alternatively, a lot of post suggest creating a UINavigationController just before presenting the popover, as shown here.
With the second method, however, won't the popover be the only controller in the newly created navigation controller? And if my view that I'm presenting the popover from is itself already in a navigation controller, the popover will NOT be in that same navigation controller, correct? It seems to be that the more appropriate thing to do would be to add the popover being created as another controller in the navigation controller that already exists (and which the controller that presents the popover is already a part of). Is that possible? Or is there a reason why the navigation controller for the popover needs to be independent from the navigation controller for the presenting controller? Or am I totally missing something here?
You have many questions, young Skywalker. :)
Creating a UINavigationController and then embedding the controller you would like to present is the way to go.
Don't get confused by all the controllers involved here:
UIPopoverController is a construct that shows an existing UIViewController in an overlay like style. UIPopoverController itself even isn't a subclass of UIViewController. The name is misleading.
So UIPopoverController hosts another controller. In your case, we let it host a UINavigationController.
UINavigationController is a subclass of UIViewController. It is a container controller and can handle a stack of UIViewControllers.
On that stack we push one UIViewController: the one you want to display and garnish with a UINavigationBar. Since Mr. UINavigationController comes with a build in UINavigationBar, he's our friend.
There is no need to subclass UIPopoverController. You just keep one static reference to it around so you can dismiss the current open popover in case you want to present another.
It does not matter where you present the UIPopoverController from. It will always be a popover. Even if presented from an existing UINavigationController. Only if you use presentViewController: you will get different results depending on the controller you're presenting from (modal or pushed on top of the stack).
won't the popover be the only controller in the newly created navigation controller?
No, the popover will contain the navigation controller and the navigation controller will only contain its root view controller (which would otherwise have been added directly to the popover as its root).
You seem to be a little confused about the relationship between the popover and the popover root view controller...
the popover will NOT be in that same navigation controller, correct
Yes, correct. The popover is effectively a window floating above all other views
Or am I totally missing something here?
Maybe... The popover would usually be used for displaying something modal, transient and smaller than full screen size. Putting a navigation controller in the popover and adding views to it is the normal approach.
Adding a navigation bar to a popover isn't hacky. A navigation bar is just another regular view. That also means that using a UITableViewController with it, the navigation bar will overlap the table view, as the UITableViewController's view property just returns the controller's tableView property. If you want to add a navigation bar above a table view, without it overlapping the table view, use a regular UIViewController and add your navigation bar and table view the normal way. UITableViewController should only be used if your only view within that view controller is a table view.
Having said that, I do agree with others that just using a navigation controller without using its navigation features is the most common approach.

IPad Split View Implement in Another View

I am creating a iPad App and it has several views to load data,but for one view i need to add split view. I dont need split views in other views. They are just detail pages. I search Through the net and found lots of tutorials based on iPad split view. But the problem is they all are creating a project as Split view project or they create a window base app and add slipt view to the delegate. I dont need to do that, I need to implement this split view only for one view. Is There any way to overcome this problem?
You can add the split view inside a Navigation Controller.
Even if the Split View is a container view controller and Apple recommends in the documentation that all containers should not be embedded in other containers, adding a split view inside a navigation controller works correctly and I never noticed any side effect in doing it.
Basically what you should do is:
- in the app delegate create a UINavigationController and use it as root view of your application window
- hide the navigation controller navigation bar if you don't want to see it (showing a split view with a main navbar on top is not nice looking...)
- then add your view controllers inside the navigation bar.
Example: imagine you have this application views sequence:
FIRST VIEW (full view = detail page)
SECOND VIEW (split view)
THIRD VIEW (full = detail page)
So you can represent FIRST and THIRD as standard view controllers (full screen), while SECOND will be a split view. Your app will be initialized by creating the main navigation controller, adding FIRST on it as top controller and using the main navigation controller as window's root view.
Than use the navigation controller push, pop methods to switch between these views or change the navigation controller "viewControllers" array directly if you don't want the recommended push/pop methods.
If you need to add special behavior to the navigation controller based on the type of view on top, just register your app delegate as navigation controller delegate (or a "main controller" object dedicated to this if you don't want to complicate your app delegate).
I am not 100% sure, but it seems to me that you can't use a SplitView just somewhere in your view hierarchy.
The Apple intended way is to use the SplitViewController as the top level controller. The left side of it can include a drill down mechanism with a navigation controller so you are ably to drill down hierarchies and the right side will present details for the item you select on the left side.
If you need a view with some kind of split mechanism in it, you probably have to code it yourself. Or even better: find some other mechanism you can use in your UI.
How are you switching your view hierarchies now? Maybe you could integrate your existing UI into a SplitViewController?

Objective-C - Understanding view controllers

I understand that view controllers help control multiple views in an application, but I have trouble understanding when to use them.
If I have an application with a main page, several views with a "hierarchy" structure, and an about page not connected with the hierarchy, what files should my application have? An appdelegate, navigation controller and view controller? More than one view controller? Just a navigation controller?
Also, should they all be contained in one .xib file, or multiple .xib files?
Any help would be greatly appreciated.
Thanks.
A good habit is to have a UIViewController for each page you want to show. If I get the structure of your app you should have a main page (with many other UIViews inside it) and another page (about page). If that's true I suggest two UIViewControllers.
The UINavigationController is a subclass of UIViewController that lets you "navigate" among the pages. It's not strictly necessary but suggested (you can also implement your self a custom navigation system, but it's easier to exploit the one Apple offers you). Another navigation system is the one based on UITabBarController, if you want to take a look.
Assuming I get the structure of your app you should need two .xib file, one for each page you have.
The app delegate is conceptually different from a view controller, you'll have just a single app delegate, automatically created by Xcode (you can, of course, modify it to fit your needs).
Each "screenful of content" (Apple uses this term) should be handled by it's UIViewController or more likely a subclass of it. The point of view controller is to handle view appearing or disappearing (going on/offscreen), device rotation, memory management, navigating to other view controllers and so on. If you are creating your UI with IB, then each of those view controllers would most likely have it's own .xib file.
Each view controller has one view (it's view property) that acts as main view for each "screenful of content" to which you then add your subviews.
UINavigationController and UITabBarcontroller are there to help you control the hierarchy of your app. They only act as containers for other view controllers and don't contain any UI except navigation bar or tab bar. Using tab bar controller you can have multiple view controllers which act exactly like browser tabs. Using navigation controller you can have a stack-like navigation where new view controllers are pushed from right to left and are popped from left to right when user goes back to previous view controller. You can even have a view controller inside navigation controller inside a tab bar controller.
If you don't want to use tab bar or navigation controller, you can navigate through your view controllers by presenting them modally using presentModalViewController:animated: and dismissing by dismissModalViewControllerAnimated:. If you send YES for animated parameter of these methods, you will get an animation specified by the modalTransitionStyle property of view controller being presented or dismissed. Possible animations are slide in from bottom (default), horizontal flip of entire screen, fade in/out and half-page curl.
There are also some Apple-provided subclasses of UIViewController that help you setup your UI quicker like UITableViewController which is basically a view controller that contains a table as it's main view and conforms to 'UITableViewdataSourceanddelegate` protocols which are required to define how each cell looks and what it contains.
On iPad there is one additional container controller UISplitViewController and one additional way to present new view controllers using UIPopover.

Resources