Bug 25385 - Navigation Controller order changed when StatusBarHidden returns true
Summary: Navigation Controller order changed when StatusBarHidden returns true
Status: RESOLVED ANSWERED
Alias: None
Product: iOS
Classification: Xamarin
Component: General ()
Version: XI 8.4.0
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2014-12-15 08:38 UTC by Allie Miller
Modified: 2014-12-17 10:00 UTC (History)
3 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED ANSWERED

Description Allie Miller 2014-12-15 08:38:11 UTC
Overview
(In the attached sample) When the StatusBarHidden method returns true, attempting to go back to a previous controller results in incorrect order of ViewControllers in the stack. 

To reproduce issue
1) Deploy attached sample to iPad simulator or device running iOS 8.1
2) Select  “Go to controller 2” right barbuttonitem
(you are now on controller 2)
3) Press “Go to controller 3” button
(you are now on controller 3)
4) Press the “<Controller 2” left bar button item

Expected results
What you would expect is to see controller 2

Actual results
You see the navigation bar of controller 1 and the body of controller 2
 
Additional information
In some cases, attempting to go back to Controller 1 results in Controller 2 being repeated twice.
This issue is not reproducible on an iPhone.

Versioning Information
=== Xamarin Studio ===

Version 5.5.4 (build 15)
Installation UUID: f6a3c61f-a7e2-4740-ba09-86314760e340
Runtime:
Mono 3.10.0 ((detached/92c4884)
GTK+ 2.24.23 (Raleigh theme)

Package version: 310000031

=== Apple Developer Tools ===

Xcode 6.1.1 (6611)
Build 6A2008a

=== Xamarin.iOS ===

Version: 8.4.0.43 (Enterprise Edition)
Hash: 840a925
Branch: 
Build date: 2014-11-16 21:03:22-0500

=== Build Information ===

Release ID: 505040015
Git revision: f93940a35458a18052f1a25e106e62ca970d9c40
Build date: 2014-11-19 15:32:41-05
Xamarin addins: dc23cbd91a3a0e1d326328e1229e86c942a49ec8

=== Operating System ===

Mac OS X 10.10.1
Darwin MacBook-Air.local 14.0.0 Darwin Kernel Version 14.0.0
root:xnu-2782.1.97~2/RELEASE_X86_64 x86_64
Comment 3 Sebastien Pouliot 2014-12-17 10:00:38 UTC
The code is incomplete wrt Apple requirements. It's documented but it's easy to miss the condition (i.e. realize it applies to your code).

When you're inside an UINavigationController then your UIViewController you'll be pushing are effectively _child_ view controllers. If the child changes some global state then the parent must known about it (only a single logic can be applied to global state like status bar visibility).

For some reason (unclear to me, but I assume there are valid reason(s)) Apple did not make this the "default" mode for UINavigationController, forcing you to DIY. Note: child vc that do not follow Apple rules often ends up with really weird behaviour (and this case is one of them).

To fix this you'll need to add your own UINavigationController subclass, simply :

	class Nav : UINavigationController {

		public override UIViewController ChildViewControllerForStatusBarHidden()
		{
			return PresentingViewController;
		}
	}

that will tell the UINavigationController that it's currently presenting child is in control of showing/hiding the status bar.

Then change FinishedLaunching to do:

	globalNavigationController=new Nav ();
	window1.RootViewController=globalNavigationController;