I have struggled to find a solution with the many similar questions and answers so I'm going to post my project here
My code does the following:
1) Creates a "container" view controller which is actually a scrolling view with 3 pages (left page, middle page, right page).
2) I just coloured the pages so you can tell the difference
3) The middle page has a view controller attached to it which contains a button
4) Pressing the button on the middle page will display a UITableViewController
5) Tapping the "Done" button should dismiss the UITableViewController
In portrait mode, no problems can be seen. In landscape mode, the UITableViewController pops up just fine with the correct (landscape also) orientation. However, when popViewController is called, this seems to make the device think that it is is portrait mode, so it rotates the tableview to portrait mode prior to the disappearing animation.
My view controller with the button is then also messed up because of this portrait change. If I rotate the device again, it returns back to normal.
This is a problem on both iPod and the iPhone 6.1 simulator for me.
Can somebody please have a look at my code and tell me what I'm doing wrong? (Big ask, I know, but hopefully that will also help somebody else out).
Thanks
I found the solution according to Apple's documentaton. If I create a separate portrait VC and landscape VC - as per the AlernateViews sample, it works correctly.
Related
Everything is in the title, I don't know why and I'm sure the answer is right in front of me but when in landscape mode, my modally presented view goes full screen and I can't dismiss it by swiping down. Is it a normal behavior ? Is there a way to make it possible ?
I've searched for an answer but I haven't found anything yet. I tried to play with the Attribute Inspector of my view, especially the modalPresentationStyle but nothing is working.
I've attached screenshots of my storyboard, no code is involved, the button is triggering segue set to "present modally". When in portrait mode, everything is fine. I'm using Xcode 12.1.
Thank you for your help !
Yes, this looks like the default behavior. Even in native apps, you can't dismiss any modal presentation in the landscape.
The reason for this seems clear. In the landscape, it is presented fullscreen. Due to the full-screen presentation, it will not be an obvious gesture to swipe down to dismiss. And presenting the same as portrait mode is not possible because of the height available.
Update: Solved. See fix at bottom.
In my iPad app which supports all orientations, if the app is loaded in landscape, weird things happen:
Alert views appear in portrait, even though the rest is in landscape
Rotating the iPad from landscape to portrait does not trigger a rotation (nor does it trigger any of the shouldAutorotate style methods).
Rotating the iPad 180 degrees (to "other landscape") does trigger rotation, and after this, the iPad behaves like normal (i.e. rotates correctly to portrait and landscape when rotated).
Alert view screen below. Weird, weird. Any ideas why this might be happening? It only happens when loading in landscape -- loading in portrait and then rotating to landscape works just fine.
Solution: This problem occurred because I was adding a UIViewController (modally) on top of the main view controller as soon as the app finished loading (more specifically, in the app's viewDidAppear: method).
iOS sends a number of (4) shouldAutorotateToInterfaceOrientation: calls to the current/main view controller after things have started up, to figure out which orientations are currently supported. When I added the other VC so soon, this occurred in the middle of the aforementioned calls. Thus, I only got one or two calls (for "portrait", because it starts with portrait).
The main view controller was then left with a default support of "NO" for the landscape orientations, but the newly added view controller (which is also asked about orientations) now happily responds yes.
If I had removed the other VC (which is in landscape), I would have realized that my main view controller was stuck in portrait. So I had a portrait view, on top of which there was a landscape view. The alerts and such heeded the orientation of the former, hence the disastrous results above.
Additionally, if I tried to rotate to portrait, I couldn't, because the main view controller was already in portrait. Rotating to landscape was also impossible because the other view controller is already in landscape. Only when I did the "landscape but that other one" rotation, did both view controllers agree that rotation was required, and thus the device rotated.
The fix in my case was to simply put the creation of the other controller at a slight delay. using performSelector:withObject:afterDelay. -- 0 seemed to work but I just put it at 1 to be sure. It looks a bit weird, with the main vc appearing and then the other vc, but it's better than the above.
This problem occurred because I was adding a UIViewController (modally) on top of the main view controller as soon as the app finished loading (more specifically, in the app's viewDidAppear: method).
See above post for details on solution.
Use UIAlertController instead of UIAlertview.
First of all, my code isn't complex - in fact it's just two sample programs from "Beginning iPhone Development: Exploring the iPhone SDK", combined into one program. I took the ViewSwitcher application, which switches between a blue view and a yellow view, and replaced the YellowViewController with the CameraViewController from the camera application.
I have three ViewControllers total. SwitchViewController just switches between BlueViewController and CameraViewController.
Inside CameraViewController, I'm trying to use a UIImagePickerController to choose an image. The picker is presented with presentModalViewController. The catch is that I want to do this in landscape orientation.
Everything works fine under 2.2.1, and everything works fine in 3.0 in portrait mode.
In 3.0 under landscape orientation, however, things break. If I set SwitchViewController to landscape orientation, my screen goes white when I try to present the picker. If I rotate the iPhone a few times, I can see a corner of the picker, which apparently was displayed off screen.
If I set CameraViewController to landscape orientation, the picker doesn't come up at all.
I think this page may have a clue when it says "The most prominent change [in 3.0] I can see is that the modal view controller will always use the application frame instead of the parent view controller's frame." I don't understand exactly what that means, though.
Any help is greatly appreciated. Thanks!
I believe what that means is this: Modal views always use the full screen, even if the parent view controller that invokes them controls a view that is only part of the screen. This makes sense for standard modal views like the camera picker, but I can see why someone who creates a custom modal view might want it to be smaller.
Not sure if that really helps solve your problem though.
Question -- what happens if you bring up the modal view and THEN rotate the phone?
You must have used addSubview in your parent view controller, try using presentModalViewController:.
I have had many successes programming the iPhone in Landscape mode, but I have been unable to get the Apple PageControl demo to run in Landscape mode and render the content correctly. The demo uses the AppDelegate class as an implicit ViewController which manages a UIScrollView, and the AppDelegate creates a set of UIViewControllers for the ScrollView's contents, 1 controller per page. In addition there is a UIPageControl object that the AppDelegate manages.
I can get the demo code to run in Landscape mode, but the contents always render as if they were in portrait mode, so while the simulator displays he device in Landscape mode, the pageControl is always on the side of the screen.
If anyone has gotten the contents to rotate correctly, I would really appreciate an explanation of how you got it to work.
I think it doesn't work because the scrollview is attached to window, and the window doesn't have a autorotate method like a view, it seems. If you put the scrollview in a view and then that view in the window, and the views controller has the shouldAutorotateToInterfaceOrientation method defined, it works. However, there is still a bit more work to do as the bounds of the pages are now wrong and need to be reset.
My application is pretty simple: it starts up with a view controller that holds a table view (in grouped view layout) with a few options. When the user taps on one of the options, I push another view controller onto my navigation controller.
This second view controller simply displays a UIImageView, and the user can change the screen orientation on this view controller between portrait/landscape modes. This works just fine, and all is happy.
However, if the user taps on the "Back" button on my navigation bar while on the landscape mode, the first controller's layout is all messed up. See below for before/after screenshots:
(source: pessoal.org)
(source: pessoal.org)
Any clues on how to force the first view controller (second screenshot in this post) to stay within the portrait screen orientation?
There does not appear to be a way to do this using the documented methods.
I have filed a bug for this: rdar://6399924
"There is no way to always restrict a UIViewController to one orientation"
You can see it on open radar (along with a link to sample code to reproduce the problem) here: http://openradar.appspot.com/radar?id=697
Like someone on the open radar suggested, a workaround is to disable "back" button while in non-portrait:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
// don't let user press "back" button in landscape - otherwise previous view and the rest of the application
// will also be in landscape which we did not feel like testing yet
self.navigationController.navigationBarHidden = (UIInterfaceOrientationPortrait != self.interfaceOrientation);
}
There is a solution to do that : it's to use a view controller and adding its view to the window. then in that controller you force landscape in the shouldAutorotate... methode. It works fine, but be sure it's necessary for your project to use that, because it's not very smart to force the user to turn his iPhone. By the way, here is an example code if you need it.
http://www.geckogeek.fr/iphone-forcer-le-mode-landscape-ou-portrait-en-cours-dexecution.html
I wasn't able to get this to work the way I wanted. You ought to be able to set a particular orientation for a ViewController, but the NavigationController doesn't seem to always do the right thing.
I ennded up re-designing my screens so that they all work in either orientation. That might be extra work, but it "feels" more natural, anyway.