presentingViewController is nil when using presentViewController:animated:completion: in iOS 8 - ios

Wondering if anyone else has encountered this issue recently...
For one of my view controllers , only on iOS 8, after calling presentViewController:animated:completion:, the presented view controller has self.presentingController as nil. It is fine on iOS7, and also does not happen on another view controller.
The documentation says that it should be set, as long as the presented view controller was presented modally. Given it works in iOS 7, could this be an iOS 8 bug?
I've been able to get around it using a view container containment approach, but it would be good if someone has seen this before and knows the root cause that triggered this behaviour.
thanks

Had a similar issue with iOS 8, where presentingController is nil when checking the value in viewDidLoad.
When viewDidLoad is called, there is no guarantee that the view controller hierarchy is loaded in the navigation tree. Moving the logic to a later stage (for example: viewWillAppear) should resolve that issue as presentingController should be loaded by then.

Related

Weird UIViewController hidesBottomBarWhenPushed layout bug that only occurs the very first time a view controller is pushed

I'm really at a loss with this one, especially considering it has previously been working fine and I can't find anything in my commits that would have broken it.
I have a UITabBarController as the master view of a UISplitViewController. Each tab in the UITabBarController has its own UINavigationController that manages a stack of child VCs.
The issue is that any child VCs that have hidesBottomBarWhenPushed set to true results in a glitchy transition, but only the very first time any UINavigationController push occurs.
Here is a video of the transition bug
As you can see, it appears as if the safe area is collapsing on transition (and indeed, this does not occur on iPad or any other iPhone that lacks a bottom safeAreaInset. Yet, on the second (and all subsequent) push, it behaves perfectly fine.
The only thing I can think of is that I'm implementing the UISplitViewControllerDelegate methods to ensure Show Detail segues occur as a push rather than a modal when on the iPhone. However, the issue still happens with a regular push (bypassing the delegate methods altogether).
The various view controllers are all the standard base classes with no overridden layout behaviour, and I'm not implementing any custom transitions or transition coordinators.
Any thoughts on what the issue might be would be greatly appreciated.
So I managed to fix it. I was performing a modal segue before the UITabBarController was coming on screen. Apparently that messes up the layout, as I was able to confirm via a minimal replication. Changing the segue presentation type to "over full screen" rather than "default" stops the underlying UITabBarController from being removed from the view hierarchy and fixes the issue.
While that's six hours of my life I'll never get back I hope it helps someone in future.

Dismissing modal view controller stack

Given the following view controller layout.
We build a stack of modal view controllers by first presenting B on A and then presenting C on B. According to the Apple documentation on dismiss(animated:completion:), calling it on A should actually dismiss the topmost view controller (C in this case) in an animated fashion and all intermediate view controllers without animation. What happens though is that C gets dismissed without animation and B is dismissed in an animated fashion.
I put up an Xcode project on GitHub that replicates that behaviour. Am I missing something or am I misunderstanding the documentation here?
After poking around the web and trying out various 'solutions' it is clear this is an actual bug within iOS. It has been present since iOS 8... and is still present in iOS 10. It was originally reported in iOS 8, but the solution was never validated and Apple automatically closed the radar due to inactivity.
I have filed a new radar as this is in direct contradiction to the documentation for dismissViewController
If you present several view controllers in succession, thus building a
stack of presented view controllers, calling this method(means
-[UIViewController dismissViewControllerAnimated:completion]) on a view controller lower in the stack dismisses its immediate child view
controller and all view controllers above that child on the stack.
When this happens, only the top-most view is dismissed in an animated
fashion; any intermediate view controllers are simply removed from the
stack.
Clear visualization of the issue, both expected and actual results. Credit to Boris Survorov for the test project and visualizations.
I've experienced the same issue and here is what I've found to be a viable workaround. When you need to dismiss the whole stack, execute this code in A:
viewControllerB.view.isHidden = true
viewControllerC.dismiss(animated: true) // or viewControllerB.dismiss(animated:true) - it should produce the same result: dismiss viewControllerC
dismiss(animated: false) // dismisses viewControllerB
This should result with the expected behavior.
I am guessing that your segue from A to B is modal as well? In that case the dismiss function called from A wants to dismiss the view, which is immediately on top of A, which is B. C just gets hidden in order to show you the animated hiding of B. In that sense you cannot stack views via modal segues and dismiss the top one with the dismiss function as you described if you go that far back. The dismiss would work as intended if called from B to dismiss C though.

Unwanted popToRootViewController

I have a older iOS app that I am working on a update for. Compiling with 8.2 and 8.3 SDK I get unwanted pops to the root view controller, running on 8.3 or 7.1 iOS. Depending on the specific view configuration when I add the 2nd view to the stack I will get a instant, after viewDidAppear, pop to the rootViewController from the 2nd view or 3rd view on the stack. I have breakpointed all my popTo statements and non of them are causing it. I am getting no indication of the cause. Are there any debug tools that can help me find this?
You can subclass the navigation controller and override the popToRootViewController method with an implementation that just calls super. Put a breakpoint in there and you should be able to pinpoint the cause. (Make sure you replace the default navigation controller with the subclass).
If popToRootViewController still does not get called, the other view controllers might be getting deallocated or dismissed for some reason.

self.presentingViewController broken on iOS 8?

I'm experiencing something really weird :
Create an extremely basic single view project, and add a second view controller to the storyboard, along with a modal segue from the first to the second. Initiate the segue from the view controller and trigger it programmatically with performSegueWithIdentifier:.
In the viewDidLoad of the modally presented view controller, add this log :
NSLog(#"%#", self.presentingViewController);
Now run the app on iOS 7, you should get a log like this one :
<ViewController: 0x7fa8e9530080>
Which is just the reference of the initial view controller of the app, which presented the modal view controller.
Now run the exact same thing on iOS 8, and you will get :
(null)
What's going on here ? Is it a known issue ? Of course I'd expect the exact same behavior on both systems.
Thanks ... Formalizsed as answer.
viewDidLoad should really be used for initialization, At this stage, there is not guarantee that the receiver's controllers view hierarchy has been placed in the navigation tree. If that is your intent, you should override viewWillAppear or viewDidAppear. Whilst it works in earlier versions, the docs clearly state that it should be used for additional initialization. It certainly sounds as though in iOS 8, the receiver's initialization is being performed earlier

Unwind Segues not working on Xcode 6

I just downloaded Xcode 6.0.1, and I tried running my app in the simulator. All of my unwind segues are not working. All of my code is in Objective-C, I have NO Swift whatsoever. The segues worked perfectly fine before I updated Xcode.
Am I the only one with this problem?
UPDATE: This has been fixed with the release of iOS 8.1.x
After a lot of fiddling around with this, my experience is that only view controllers presented modally are affected by this issue. The work around in this case is to set your segue presentation to Current Context instead of Default.
Credit to this SO poster https://stackoverflow.com/a/25842508/401092
This was a bug affecting iOS 8.0(and .1 and .2) - view controllers presented modally wouldn't perform unwind segues - the unwind method wouldn't be called.
This issue appears to be fully resolved with iOS 8.1 beta. Note that iOS 8 doesn't automatically dismiss the modally presented view controller while on iOS 7 it does, so if you need to support both you'll want to detect if it's being dismissed in the unwind method and if it's not then manually dismiss it.
It worked for me!
So in my case I had a view controller presented modally and when I wire an unwind segue to a button, the prepareForSegue method was never called and the unwind method in the root controller never called neither.
Change to current context and everything is working.
Thanks

Resources