Coordinates in landscape mode iPad app correspond to portrait mode - objective-c

I'm having a weird issue with an iPad app I'm writing.
I want to add a UIToolbar to my main view controller (set as root view controller in the app delegate). Within this main view controller, I support only landscape orientations. When I set the frame for my toolbar, however, it seems that the ipad still thinks it's in portrait mode! What I mean by this is when I run this line:
[_toolbar setFrame:CGRectMake(0, 0, [[self view] frame].size.width, 44)];
The width of the toolbar is only 768, rather than 1024, even though the width of the screen at this point is clearly 1024, because the toolbar extends across only 2/3 of the screen. I'm having similar problems with placing subviews, and getting really weird placement on my main view controller.
Has anyone else run into problems like this? If so, how did you fix it? Thanks!

You should use the view's bounds, instead of frame, and you should not execute your code too early in the view's life cycle.
If you invoke your code from the control's viewDidAppear, then I guess it will work. But if you invoke your code from viewWillAppear, then it is too early.

Related

iOS10 UIImagePickerController embedded as ChildViewController, not showing its subviews correctly

I am using an UIImagePickerController embedded in a square view container. It worked fine on iOS 8 and 9. On iOS 10, the internal objects of the UIImagePickerController will not stretch to the full width of the camera picker controller. See 2 screenshots:
The selected view in the view inspector is: CAMPreviewView (inside UIImagePickerController).
Here is the code I use for embedding the UIImagePickerController as a subview:
- (void) presentCameraInWindow {
[self addChildViewController:self.videoRecorder];
[self.cameraHolder
addControls:#[self.videoRecorder.view]
align:VerticalAlignStretchToFullHeight
withHeight:self.view.bounds.size.width
verticalPadding: 0.0f
horizontalPadding:0.0f];
[[self.videoRecorder view] setNeedsLayout];
[self.view layoutIfNeeded];
[self.videoRecorder didMoveToParentViewController:self];
}
NOTE: addControls is a vertical Layout engine i built which I use everywhere. It creates constraints automatically, programmatically, so i don't have to.
I call this set up in viewDidLoad.
The same issue occurs, if i don't use Constraints, and I set the frame of the UIImagePickerController manually.
We can clearly see in the view inspector that the UIImagePickerController is laying out correctly (to the full width and height of the container view, but it's internal subviews are not).
Also: Using AVFoundation directly is not an option right now, because of the effort involved.
I was not able to embed the UIImagePickerController in a subview that had a smaller frame than that of the Parent View Controller. So I embedded the UIImagePickerController in the self.view of the View controller housing it. Then I sent it to back, putting overlays on top of it as needed. I also ended up moving up its frame by a certain amount, since my app works with square videos. So it doesn't mind if I move its frame partly outside of the visible screen coordinates, as long as I don't try squishing its frame smaller than the size it wants to be. If I do that, then the internal viewfinder subviews inside UIImagePickerController start to lay-out unexpectedly (cut off). Again, this issue occurs on iOS10 only.

AutoLayout fails, black background and autoresizing masks show up in any case

I made a UIView in a StoryBoard containing six UIButtons.
I wrote some constraints to support landscape mode as well as portrait mode and put them in two different Arrays: portraitModeConstraints and landscapeModeConstraints.
When the mode changes, the old constraints are removed and the right array gets added.
When i load the view in portrait mode there is no problem. All Constraints work fine, but wen i turn the iOS-Simulator, i'm getting a lot of warnings. But my constraints work, i tested them. The constraints that make problems are the ones from the autoResizingMask. So i turned them of on my view controller using
[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
This made no change. So i debugged a little bit and found out that there is no difference between setTranslatesAutoresizingMaskIntoConstraints:NO and setTranslatesAutoresizingMaskIntoConstraints:YES
That is really strange and i can't understand this behaviour.
However, i deleted the constraints manually like this:
[self.view removeConstraints:self.view.constraints];
Now, the constraints worked perfectly in both portrait and landscape (the UIButtons were at the right positions) but the background of my UIView turned black and the background image was gone.
EDIT: When the device will rotate, a function on my viewController is called:
willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
In there i check wether the toInterfaceOrientation is landscape or portrait.
When it is portrait, i do this:
[self.view removeConstraints:self.landscapeModeConstraints];
[self.view addConstraints:[NSArray arrayWithArray:self.portraitModeConstraints]];
[self.view layoutSubviews];
And when it is landscape i do this
[self.view removeConstraints:self.portraitModeConstraints];
[self.view addConstraints:[NSArray arrayWithArray:self.landscapeModeConstraints]];
[self.view layoutSubviews];
Stack with the same problem, when controller is embedded in nav controller, and i'm doing self.view.setTranslatesAutoresizingMaskIntoConstraints(false) the view is black. Actually there is no reason to set transl..... on self.view. You need to apply it to subviews. Auto Layout Guide

Is there a function to know the useableSize of a view?

It must take into account:
statusBar (which can be 40 points if you have hot spot)
TabBar
NavigationBar.
Basically at viewDidLoad I see that my view has a size of 320*480.
I wonder where did iOS decide that as the screen size of my screen. I use UIStoryBoard.
So, on viewDidLoad, I intended to resize that.
I am not even sure if this is the right approach.
Note: the issue I am facing doesn't seem to happen if I do not use storyBoard.
At viewDidLoad, when I use XIB, the content of self.view is correct, namely 416, instead of 480, due to UInavigationController and UITabBar
Try overriding the UIViewController viewWillLayoutSubviews method. The view's frame will be set by then.
In the viewWillLayoutSubviews method, the view controller's main view is the size you need to know. It has been adjusted for status bars and nav bars and tools bars and tab bars. It also takes into account orientation. There is no single method where you can ask what the size will be. Besides, there is no need to ask such a question. Create all the subviews you want in viewDidLoad. But lay them out based on the view's size in viewWillLayoutSubviews.

presentPopoverFromRect is displaying a popover sideways on rotation

-I have a UIView.
-This UIView has a UIButton that when clicked makes a UIAlertView appear.
-Within this UIAlertView I have another UIButton that when clicked calls buttonClicked:
-Within this buttonClicked: method, I call presentPopoverFromRect with a custom view inside. (hourKeyboard is the custom view)
-(void)buttonClicked:(id)sender
{
if(self.hourKeyboard==nil)
{
self.hourKeyboard = [[HourKeyboardViewController alloc] init];
self.hourKeyboardPopover = [[UIPopoverController alloc] initWithContentViewController:self.hourKeyboard];
}
[self.hourKeyboardPopover presentPopoverFromRect:[sender bounds] inView:sender permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}
In normal portrait mode, this works great. The popover spawns just to the right of the button, with the arrow correctly pointing left to the button.
There's 2 problems that arrises:
1) While this popover is visible, when you rotate the screen the popover rotates slightly incorrectly (it doesn't reposition it's own x and y position)
2) If the popover is not being shown. If you rotate the screen, then call "buttonClicked", the popover will appear, however, its being shown sideways above the button with the arrow pointing "down" towards the button (technically left in relation to the sideways popover view). If you dismiss it, rotate the screen, then call "buttonClicked", the popover now appears upside down with the button pointing "right" to the button (again, technically left in relation to the sideways popover view)! Repeat to make it sideways again, then right-side up again.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
My thinking:
1) I believe I can just reposition the x and y, however, I've also read that you should dismiss the popover and present it over again on a rotation. I'll see if I can get the first one working, however I'm more concerned about the second problem.
2) I have no idea how to fix this rotation issue. It seems that when you rotate to landscape without the popover being visible. And then you call presentPopoverFromRect, the popover is created with the iPad thinking it's still in portrait view by mistake. That's the behavior it's giving, however, I'm not sure how to make the iPad not make this mistake.
-=-=-=-=-=-=-=-=-=
Thanks again for any help you can provide!
-=-=-
Slight Update:
1) It was easy to just dismiss the popover from the main view on rotation. And this seems to be the general way everyone deals with this issue.
2) Trying out various things such as changing the frame, using CGAffineTransformMakeRotation, and others...but no luck thus far
-=-=-
Another Update:
2) After a lot of testing, it seems to be a direct issue with UIAlertView. If I place the view within UIAlertView (currently doing), the AlertView doesn't tell the popover that the screen is rotated...thus creating the issue
It looks like the only way to fix this is to drop the UIAlertView completely. Instead of showing the UIAlertView, I'll disable the various background views manually (like Alert View was doing) and then show a custom UIView that looks darn similar to the AlertView. From there, I should be able to show the popover without any issues. I'll let yea know how it turns out.
-=-=-=-=-=-=-=-
Final Solution:
I ended up just creating my own view, and having that view imitate a UIAlertView. Then when I spawned the popover, I placed it in the root view controller. Worked much MUCH better, but required more work since I had to manually create my own View instead of the premade UIAlertView. Either way, apparently UIAlertView fails at telling a UIPopoverover subview what rotation it is in.
dismiss the popover in willRotateToInterfaceOrientation and show it again in didRotateFromInterfaceOrientation.
It works with no problems.
EDIT:
Sorry, I misunderstood your second problem.
If some part of your view hierarchy is displayed with bad orientation, one of your controllers is probably missing shouldAutorotateToInterfaceOrientation method.

iPhone view controller view shifted down 20 pixels when rotating to landscape

I am trying to implement a custom tabbarcontroller using a UIViewController and a UITabBar. Everything is working fine so far, except when I rotate the device to landscape, the UIViewController shifts the entire view down 20pixels, creating a black bar between the status bar and the view. Even when the view is rotated back to portrait orientation, the view is still shifted down 20pixels.
What do I need to do to remove the black bar? Do I have to perform custom rotations? If so, where should I insert these rotations?
Before rotation:
After rotation:
I've experienced this same issue.
This discussion was helpful: UIWebView on iPad size
Tony's answer helped me discover that when you create a subview it's helpful to setup code similar to this:
UIWebView *webView = [[UIWebView alloc] init];
webView.frame = self.view.bounds;
If you post some of your code I may be able to provide more specific advice.
Rather than shifting all views down, try DELTA properties in Interface builder.