Why is there a 20-pixel-high dark overlay over my app's navigation bar? - iphone

Once again, I'm almost entirely sure this is something dumb that I'm doing, but I've been banging my head against this one for hours & am getting nowhere.
I'm trying to restructure the view hierarchy of my app. I need to be able to detect user interface orientation changes globally in order to correctly rotate a "Loading" view displayed when the app is downloading content. (device orientation changes seem to fire at different times, causing the view that needs to respond to these events to rotate sporadically).
The app previously added a UINavigationController's view to the main window. I modified the hierarchy to add the view of a UIViewController subclass to the main window, and added the view of the UINavigationController to the subclass's view. The UIViewController subclass manages the display & rotation of the "Loading" subview, and I was expecting the rest of the app to continue behaving normally, as inserting one extra empty view into the hierarchy didn't feel like I was changing too much.
My initial problem was the positioning of the UINavigationController - it was 20 pixels too low, resulting in a gap between the status bar and the navigation bar, and cutting off the bottom 20 pixels of the tab bar. I was able to adjust this by setting the frame property of the UINavigationController's view to the bounds property of the UIViewController's view, which corrected the position.
However, now I'm stuck with a 20-pixel-high dark "overlay" on top of my navigation bar. If I were to guess, I'd say it was black with 50% opacity. Touch events on this bar don't work (e.g. if I try to tap the "Back" button through the overlay, nothing happens). The fact that the height is equal to that of the status bar hasn't escaped me, but I'm at a total loss as to what could be causing it.
I hate feeling this stupid, so if anyone has any insight into this problem, you'd really make my day. Thanks in advance!

OK, a few things pop out from your post.
My initial problem was the positioning of the
UINavigationController - it was 20
pixels too low
This makes me believe it is related to your new problem.
I was able to adjust this by setting
the frame property of the
UINavigationController's view to the
bounds property of the
UIViewController's view
This sounds like the view it was loaded onto was offset 20 pixels, and when you set it to the bounds, it repositioned it on the windows view space.
Touch events on this bar don't work
(e.g. if I try to tap the "Back"
button through the overlay, nothing
happens)
This is the big thing. If touch events aren't being sent to the view, then what that means is that the OS doesn't see a view where you are pressing (or rather the view you want it to), so that view doesn't get the message to do something.
From what you have said, I believe your problem is with your base view controller that you just added. Try redoing the frame on, making it conform to where you want. Then take out the code you put in to set the navigation controllers frame. The navigation controller should fit to the view you added too, and once you have that main view where it needs to be (20 pixels higher apparently), then everything should work.

Related

How to get the visible view size in iOS13 when presenting a view controller

In iOS13, the default way when presenting a view controller was changed to the "sheets/cards" view. As I’m not using auto layout (why not, is not really important and relevant), I rely on getting position of elements based on the frame of the view.
Now, the problem with the new method is, that the view frame doesn’t really reflect the actual content size visible on the screen anymore. E.g. if I have positioned a UIButton at the bottom on the view controller based on the view.frame bottom coordinate, it will be now cut off, as the view is actually moved down in the amount of the nice "sheets/cards" visual indication at the top. The same problem is even more evident in an iPad, where centring another view in the view controllers view will be offset, due to the fact that the default presentation style is now a "sheet" in the middle of the screen.
I’ve currently changed everything to force the full screen version, but it would be nice to use the new fancy design.
Anybody has any idea how to get the actual visible rect/coordinates in the new style without changing things to auto layout?
Here are how they look. The "flower" is centered in the view and the X button should not be so close to the bottom or missing completely in the iPad version.
Finally figured it out. As I was setting the positions of items in viewDidLoad, the frame was not calculated correctly, thus resulting things being laid out incorrectly. When resetting the frame and positions in viewDidLoadSubviews, the positions were placed correctly.

Unable to get the correct frame for UIViewControllerAnimatedTransitioning to UIPageViewController

I have been battling this transition animation and I am pretty much out of ideas. I am attempting something similar to going from the collection to the individual photos in the Photos app on iOS.
It all works to my satisfaction with the exception that the frame for the "big" detail view of the image is not correct. It is the right size but it is about 87 points closer to the top of the screen compared to the actual position of the image in the final state. This is pretty much the same height as what is above the "safe area" (iPhone X titles + navItem) and irritatingly close to what is also below the safe area (toolbar and iPhone X home area).
I have Googled (and "SO'd") a bunch of different solutions to similar sounding problems. E.g: UIViewControllerAnimatedTransitioning with Safe Area Insets on iPhone X
I have downloaded and perused example code from Github. E.g: https://github.com/SamStone92/CustomTransitions
It seems to me that I have something in my view (controller) hierarchy which is complicating this more than most. I would love some hints as to what might be causing the problem and how I might go about fixing it.
My hierarchy is:
NavigationController containing the root VC with a UICollectionView.
Tapping a cell transitions to a UIPageViewController for a "detail view" where I can page between items in the collection.
UIPageViewController has a bottom toolbar in addition to the navigation bar.
The content ViewController has a ScrollView with a UIImageView in it to get some zooming.
Seems like the common approach is to add the destination view to the container, force a layout pass and then get the frame. I have tried many variants of this with and without converting the coordinates. (they appear to always remain the same before and after conversion)
My Theory
I am leaning towards the UIPageViewController being the complicating factor. But I have not been able to untangle how to get the correct coordinates.
The destination view (in the animation) is not the content view but the PageVC view which in turn may or may not have added the content view, adapted it to the navigation item or the toolbar.
Seems like viewWillAppear on the content VC does not have the right coordinates. I can tell that the detail content view is getting a call to viewWillLayoutSubviews after that and also after all the animation delegation stuff has had its turn.
This is a color overlay of my main views. Grey is the top and bottom areas outside the safe area. Blue is where the transition animates to before revealing the green, underlying actual position it should have animated to.

Why Status Bar rotates and view remains portrait

My rootViewController is a UITabbarController and contains UINavigationControllers.
In order to restrict rotation, since iOS6, on some but not all views, I have subclassed both of the these controllers to respect the shouldAutorotate response of their topmost or visible view.
This all works just perfectly... most of the time.
In one case, starting from a view (UITableviewController) that does not allow rotation.
I push a view that does allow autorotate, rotate to landscape then back to portrait.
Then when I pop the view, all appears well.
But now if I rotate the device, the status bar alone rotates, leaving a blank space at the top and covering a part of the left side of the current view. The current view does not rotate (as it should not). Only the status bar rotates, back and forth. The view remains responsive, receives touches and works as normal, doesn't resize or respond to rotation in any way (as it should not).
This behavior continues until I kill and restart the app. Once it happens I have found no other way to make it stop. On restart all works properly again and will work properly for an indeterminate duration. I can sit there pushing, popping, rotating back and forth to my hearts content with no issues.
I have never been able to recreate this in simulator.
It happens for no apparent reason, I cannot make it happen. I'd say 85% of the time it works properly. I thought I had it fixed many times when it did not occur for days or even weeks. Then, out of the blue it happens again.
I cannot find a post in any forums which describe this behavior, so I am not finding even a place to start to debug. How could the status bar swing from top to side and the view does not resize or rotate or respond in any way. If I knew how to make that happen, I would have a place to start.
I experienced the same problem when adding a subclassed UIWindow (in my case, a status bar overlay).
The solution was to set the rootViewController of this new UIWindow to a subclassed UIViewController that had -(BOOL)shouldAutorotate implemented. This prevented the status bar from rotating when it wasn't supposed to.

Iphone View Rotation not functioning properly

I have a simple 1 screen app, with 1 View.. the view contains
a button, an textbox and a button across the top
A segmented controller across the bottom
and a MapView in between.
In portrait mode all is right with the world.. So I decided to begin to allow Orientation change...
in IB all views and elements and even the root window have autoResizeSubviews set
in My AppDelegate and my viewController I have also programatically added SetAutoResizeSubviews to yes explicitely I have set the autoResizingMask in the Root Window and the View Controller to FlexibleWidht | Flexibile Height
I have added the shouldAutorotateToInterfaceOrientation in my ViewController to always return true.
Yet, it doesn't work.. Or should I say it doesn't rotate properly.. in both portrait modes everything looks great, but both landscape modes, things don't get laid out or resized properly.. Basically all I see is the mapview, and its size gets slightly wider, but not much than the portrait mode, and it doesn't fill up the screen top to bottom.. all other interface elements with the exception of one button are invisible and it appears on TOP of the mapview.. as thought it just happened to be layed out over the view by coincidence than any design.
Anyone have any ideas what I am missing, or why?
Thanks in advance
You say "I have set the autoResizingMask in the Root Window and the View Controller" but that is a red herring. It is the buttons, the text box, the segmented controller, and the map view that have to have the correct autoresizingMask. If this view is being designed in the nib, you can set the values there and then turn the orientation right there in the nib and see what happens.
If you are unable to work out good autoresizingMask values for all those interface elements, implement didRotateFromInterfaceOrientation and perform the layout alterations in code when called upon to do so.

Laying out items in Interface Builder

So I haven't had problems with this before, but for some reason, my view seems to be shifted up. On my first view controller that I add to the subview, it seems to be shifted up 20 pixels, showing whitespace. I am following the blue lines in interface builder, and I don't do any resizing or offsets with my view or frame. I basically just alloc/init my subclass of UIViewController in my app delegate, and add the .view of that viewcontroller to my subview. Just wondering if there might be something else I'm missing??? Sorry for being so vague, i just don't see what's going on.
Looking at the MkMapView I dropped into my view, it says the x, y is (0, 20), and the width/height is 320/460. But again, for some reason it does not display properly in the iOS simualtor.
On the main view, check the settings (View Attributes/Simulated User Interface Elements) for the status bar. That's probably the 20 px culprit.
I usually encounter this problem with 44 px, in which case the navigation bar is misbehaving.