How to unwind from UINavigationController to UIViewController? - uinavigationcontroller

I'm trying to use an unwind segue from a UINavigationController subclass to a UIViewController subclass. My issues arise arise (I believe) because my navigation controller is the root view controller of my UIWindow. I attempted to set my UIViewController as the root and then modally present the navigation controller before my AppDelegate finishes launching, but that doesn't work because the view is not added to the hierarchy.
Any ideas?
EDIT:
Is there anyway to attach a segue to the top view controller of the navigation controller? I have a fairly large storyboard and would like to avoid repeating myself on multiple controllers.

I'm currently struggling with using unwind segue past navigation controller myself too but maybe that article I found can help you. It describes (with GitHub project attached) how to use unwind segues whilst under the aegis of a UINavigationController:
https://github.com/simonmaddox/CustomUnwindSegue/tree/master
PS - Regarding your Edit: If you can get it to work following SimonMaddox steps in the link I suggested, the method should then work from any ViewController under the Navigation Controller I think.

Related

NavigationController and View Hierarchy issue

I have 1 (rootViewController) view controller which is embedded in navigation controller. Then i pushed another view controller (secondViewController), which has search controller in title view. When i am trying search become first responder (Active) i got this in terminal:
Warning: Attempt to present
"AppName.CustomSearchViewController: 0x7face0c20eb0> on
whose view is
not in the window hierarchy!
This happens only in iOS lower than 11. When i embed this second view controller in navigation controller and present it modally all works good, but i need exactly pushing. How can i solve this?
I solved it! I need to make definesPresentationContext false in rootViewController to make it work on another one!

UITabBarController in UISplitViewController with Storyboard

I have UISplitViewController with UITabBarController as its master. UITabBarController contains one UINavigationController with UITableViewController as its root (it is main menu of my app).
After tapping on any cell in main menu, in UISplitViewController's detail part another UITableViewController should be presented (let's call it detail view).
In landscape mode everything works OK.
But in portrait, whet I tap on cell in main menu, the detail view is presented modally, and not pushed, like it supposed to. Also, when rotating from landscape to portrait, the main menu is presented instead of detail view, and after I click on main menu's position to show detail view, it is presented modally with no possibility to rotate or to go back.
Removing UITabBarController and setting UINavigationController as UISplitViewController's master works as I want (in landscape mode we have menu|detail views side by side and in portrait mode controllers behave like they were on regular UINavigationController). But then the UITabBarController is gone.
What I've tried:
every possible segue type - none of them works the way I want
subclassing UIStoryboardSegue to implement custom behavior depending on UISplitViewController's viewControllers param (in portrait mode it has only one view controller - master) - but I couldn't recognise classes (thank you Swift!)
What I want is to do it entirely in Storyboard (OK, custom segues doesn't count) - I want an elegant solution and I refuse to believe it's impossible.
Working on iOS 8 SDK, Xcode 6.2, iPhone 6 Plus
Unfortunately there is no absolutely elegant solution to this one (as far as I've managed to accomplish). Hoping that Apple will eventually sort it out, but in the meantime, this is the nicest way possible:
Place one custom segue instead of Show Detail
In perform method of your custom segue have something like:
- (void)perform
{
MasterViewController *source = self.sourceViewController;
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
UISplitViewController *splitViewController = appDelegate.splitViewController;
if ([splitViewController.viewControllers count] > 1) {
[source performSegueWithIdentifier:#"showDetail" sender:source];
if (appDelegate.masterPopoverController) {
[appDelegate.masterPopoverController dismissPopoverAnimated:YES];
}
} else {
[source performSegueWithIdentifier:#"showDetailSmallDevice" sender:source];
}
}
[splitViewController.viewControllers count] is here just to separate large devices (iPads & iPhone 6 Plus) and the other, smaller ones
In your Storyboard, wire up one segue named showDetail which is actually a showDetail, to the detail navigation controller, and directly to the contents view controller another showDetailSmallDevice which is actually Show
(Push)
See the example:
http://i.stack.imgur.com/GQpg3.png
EDIT: SplitViewController needs two Navigation Controllers. The solution is that you need to insert another Navigation Controller between the SplitViewController and the DatailViewController. Then, from the TableView, preform a Segue directly to the second Navigation Controller. The SplitViewControllers wants two Navigation Controllers...
Maybe a good way could be to start a new SplitViewController project on IB. There are various default methods and properties to manage a SplitViewController. You can find something in appDelegate class, it could be a good starting point.
OLD: I like Mateusz's answer, just a point that is possible to use self.splitViewController.isCollapsed for testing if DetailViewController is or it could be shown on screen. With this property there is no need to count viewControllers.
#property(nonatomic, readonly, getter=isCollapsed) BOOL collapsed
From documentation: A Boolean value indicating whether only one of the child view controllers is displayed. This property is set to YES when the split view controller content is semantically collapsed into a single container. Collapsing happens when the split view controller transitions from a horizontally regular to a horizontally compact environment. After it has been collapsed, the split view controller reports having only one child view controller in its viewControllers property.

Setup for navigation in wpf and mvvmlight

Currently getting started on a new wpf project and want to use mvvmlight. My initial thought was to have 4 buttons as navigation at top of the window and then a contentcontrol where new views would be injected when chosen from the navigationbuttions.
That is a mainwindow and som subviews that will be injected. The main VM should have commands hooked to wired up with the navigation buttons. When executed the command should send a navigation message to change a view, and this is where I get confused. Who should handle the navigation messages send and change the view in the ContentControl? I guess the ViewModelLocator is only for instantiating the viewmodels.
What is missing in getting this glued together?
Best regards
See this answer for a dialog strategy. This should be applicable to your problem. However, one word of caution when using messages in the above szenario ... call Unregistr() especially on your views.

UIBarButtonItems not showing up on UIToolbar

I have a UINavigationController with toolbarHidden set to NO.
I have added UIBarButtonItems to navigationController.toolbar.
The toolbar is displayed, but the buttons are not...
What gives?
Ok so apparently I misunderstood the usage of the setItems method on navigationController.
To remedy this I set the toolbar items on each view controller that is pushed onto the navigation controller's stack.
I guess if I wanted to have one toolbar persist through all the views I could add a new toolbar to the view controller holding my navigation controller then simply invoke setItems on my navigation controller.
I digress.

Autorotate with a UINavigationController

I am a little unclear on how to rotate views that are sitting on a UINavigationController.
I have overridden the UINavigationController object with one of my own that overrides:
(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { return YES; }
I have one view on the stack on the controller and that view is loaded from a xib with two views in it. I want to switch from portrait to landscape. Normally I would handle this by changing the view from within the nib files of the view itself. Do I have to implement the rotational code within the Navigation Controller or just within my view code?
(void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
That willAnimate code is what I'm used to using in the view itself, but I'm still not seeing the view being changed, and I'm thinking it may be that I need to access the view in the NavigationController and change that, or even override the same method in the Navigation Controller and do my view switching there.
Any suggestions? I've never actually done this before and just found out the TabViewControllers and NavigationControllers are both portrait mode only by default.
Turns out it wasn't possible to change the view because I was trying to changes the RootView on the Navigation Controller. I got around this by placing my own pseudo root view controller that never gets seen in the root spot on the Navigation stack. I overrode a few of the navigation controls to account for this so the functionality would continue the same and I'd be able to change my desired perceived root view as I needed to.
A start in the right direction can be found in this link:
http://starterstep.wordpress.com/2009/03/05/changing-a-uinavigationcontroller’s-root-view-controller/

Resources