Presented UIViewController refuses to lay out with landscape orientation - ios

I am updating a 5-year-old app (originally written for iOS 3!). I have made decent inroads in using autolayout and addressing deprecation warnings. But the old technique used for presenting a different view controller when the device is rotated no longer works reliably.
- (void)orientationChanged:(NSNotification *)notification {
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (deviceOrientation == UIInterfaceOrientationLandscapeRight && !showingOtherVC) {
// switch to other VC
othervc.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self presentViewController:othervc animated:YES completion:nil];
[self resignFirstResponder];
}
The other view controller does appear, but it's laid out sideways, for a portrait screen, not landscape, even though the device is in a landscape orientation.
How can I update this in a reasonably easy way (i.e., not a rewrite in Swift, not restructuring the app with storyboards — which Xcode doesn't seem to facilitate via copy/paste)? And, for the benefit of others who may happen on this question, what would be the more correct way to achieve this result (new VC on orientation change) if I were writing this from scratch?
Thank you.

This was a really stupid error, but in case someone else makes it and ends up here, this was the problem.
Instead of correctly returning the mask constant:
-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskLandscapeRight);
}
I was returning this other constant that autocomplete gave me:
-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
return (UIInterfaceOrientationLandscapeRight);
}

Related

Forcing Portrait Orientation if iOS

I've made a puzzle game ('WordBatch', available in the App store) and thought I had forced portrait orientation but its still rotating to landscape mode, though only the iPad. In XCode I specified it as a 'Universal' App, for all devices, and checked portrait mode only in the General tab. Even in the plist file portrait is the only orientation specified. I've tried all the suggestions in StackOverflow on this subject, but to no avail. The current code I have on place is this bit in my AppDelegate:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
and the following is in my root view controller:
-(BOOL)shouldAutorotate {
return NO;
}
but it still rotates to landscape. Any help here would be great.
You can try by applying this check:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
// The device is an iPad.
}
else
{
// The device is an iPhone or iPod.
}

Locking orientation issue in iphone

I have a structure like this
LoginViewController-->Root
LoginViewController-->UINav---->HomeViewController
Now I have to lock this orientation to portrait only for iPhone and have to provide both orientations for iPad
For the Login Controller, I wrote this
-(BOOL)shouldAutorotate{
if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPad)
{
return YES;
}
else
{
return NO;
}
}
This is working fine. I got only a portrait orientation in iPhone and both portrait as well as landscape orientation in iPad
But the same piece of code is written in HomeViewController is not working.
Is it due to the Navigation Controller which is embedded with HomeViewConroller.
Well. I got a fix for that myself. Posting the solution on what to do as it might help others too.
Just uncheck the Device Orientation checks (LandscapeLeft and LandscapeRight) in Target->General
And write the same piece of code in every controller
-(BOOL)shouldAutorotate{
if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPad)
{
return YES;
}
else
{
return NO;
}
}
This worked for me. Now I only get a portrait mode in iPhone and a landscape as well as a portrait mode in iPad.

orientation in ios ipad

I have an Ipad application which support in "landscape" mode now i want this to support for both "landscape and portrait" this project is made with "xib" files
i used some delegates but i did not get solution what i have to do
i use this code
- (void)viewWillTransitionToSize:(CGSize)size
withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
//The device has already rotated, that's why this method is being called.
UIInterfaceOrientation toOrientation = [[UIDevice currentDevice] orientation];
//fixes orientation mismatch (between UIDeviceOrientation and UIInterfaceOrientation)
if (toOrientation == UIInterfaceOrientationLandscapeRight) toOrientation = UIInterfaceOrientationLandscapeLeft;
else if (toOrientation == UIInterfaceOrientationLandscapeLeft) toOrientation = UIInterfaceOrientationLandscapeRight;
UIInterfaceOrientation fromOrientation = [[UIApplication sharedApplication] statusBarOrientation];
[self willRotateToInterfaceOrientation:toOrientation duration:0.0];
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
[self willAnimateRotationToInterfaceOrientation:toOrientation duration:[context transitionDuration]];
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
[self didRotateFromInterfaceOrientation:fromOrientation];
}];
}
-(void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
NSLog(#"Transition");
}
You should add UISupportedInterfaceOrientation key with list of orientations (you can make it with xCode UI in the target's General settings).
Also, if you need different orientations on different view controllers, you can override method
- (NSUInteger)supportedInterfaceOrientations
And you should read this adaptive interface, because in ios 8, orientation changing means resizing of view.
Below is an example of how to track the screen size initially and with orientation changes in Swift on iOS 8.
I would drop the trait collection delegate method, if you're just beginning. Programmatically working with constraints and transitions at that level is very involved and tricky. Some of it is evolving and/or not well documented, and things happen with constraint transitions behind the scenes that are difficult to figure out. You probably don't need to mess with things like that for awhile.
If you have to adjust constraint programmatically at all, to start, in general it is easier to do the layout in Interface builder, with constraints, and reduce the problem to making minor adjustments to the fewest number of constraints possible from the code, where you access the specific constraints via IBOutlet, and modify their .constant property (rather than remove/replace constraints, which is very difficult to get right).
If you're just getting started at this point in the iOS history, I think Swift is a better way to go than Objective C ( I've done plenty of Objective C programming) Swift is the future with Apple, and has some nice powerful features while getting around some problems and challenges in Objective C. And it offers many conveniences.
override func viewWillAppear(animated: Bool) {
adjustViewLayout(UIScreen.mainScreen().bounds.size)
}
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
adjustViewLayout(size)
}
func adjustViewLayout(size: CGSize) {
var width = CGSize.width
var height = CGSize.height
/* this method will be called when the view is
about to appear and whenever the orientation
changes. Adjust what you need to here based
on the incoming width and height
you can infer whether the screen is in
landscape or portrait by which dimension
is larger. Or use a switch statement
to check for specific screen sizes
and orientations. Though it may
be incomplete knowledge of layout or
a failure of design if you need to do that */
}

Can I use interface builder to my fields different positions in landscape mode and portrait mode?

Can I use interface builder to my fields different positions in landscape mode and portrait mode ? (Completely different, so I can't just use the layout properties) ?
Or is the code the only way to go ?
thanks
You can use willRotateToInterfaceOrientation method. When you change device orientation it will call..
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
-(void)willRotateToInterfaceOrientation: (UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration
{
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation))
{
[label setFrame:CGRectMake(20, 52, 728, 617)];
}
else
{
[label setFrame:CGRectMake(20, 52, 728, 617)];
}
}
i would say go for the code if the fields shared by portrait and landscape mode are same. In case of having different objects in each mode wont be a good idea.
You can keep two UIViews in interface builder, and when user rotate device, you can hide one and show another based on orientation. Can you please try the following lines of code?
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
if(([self.navigationController.visibleViewController interfaceOrientation] == UIDeviceOrientationLandscapeLeft) || ([self.navigationController.visibleViewController interfaceOrientation] == UIDeviceOrientationLandscapeRight)){
self.viewLandscape.hidden = NO;
self.viewPortrait.hidden = YES;
}
else {
self.viewLandscape.hidden = YES;
self.viewPortrait.hidden = NO;
}
}
Here are the approaches that you can use. Best approach is on the top
1. It's better to use auto layout for adjusting your views.
2. Auto layout + code
3. Code only.
4. You can make two views for your xib one for landscape and one for portrait. And show and hide as per the orientation. But in this you need to sync all your portrait views with landscape views (properties like text) and vice versa. This is easy to maintain but you have to take extra headache for syncing the properties of each view.

Why is my ModalView displaying in portrait mode?

Hopefully somebody can point out what I'm doing wrong with my Splash screen here. The problem is that the screen is displaying in portrait mode, not landscape...
- (void)showSplash
{
UIView *modelView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024 , 748)];
UIViewController *modalViewController = [[UIViewController alloc] init];
[modelView setBackgroundColor:[[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"Splash.png"]]];
modalViewController.view = modelView;
[self presentModalViewController:modalViewController animated:NO];
[self performSelector:#selector(hideSplash) withObject:nil afterDelay:5.0];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
Thanks in advance for the help.
Looks like you are writing app for iPad. If so, you have to support both landscape as well as portrait orientation otherwise Apple will reject it. I would suggest that you should use two different images. Image specifications are as follows:
Default-Landscape.png (1004 * 768)
Default-Portrait.png (748*1024)
(I am assuming that you are showing status bar if not add 20 pixels to height of an image)
That's it, create these images and add it to your project. And you are good to go. No Need to write any additional piece of code too..
And ya make it
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
You shouldn't rely on a function in your code to display the splash screen. Just define them as the previous answer from Sumit Lonkar explains.
If you do it in code, I believe at the start of the application the orientation is always considered as portrait, then the transition to the actual orientation is triggered. This explains why your code displays first as portrait and most likely there is nothing else in the code to handle rotation. Besides, the purpose of the splash screen is to display something while the app is loading, so if you put it in code you lose the purpose.
By doing it the Apple way you leave it to another Apple process that runs before looking at your code and it will work.
Regarding the orientation supported I have on my iPad some apps that support only landscape (TapZoo for example) so it should be ok with Apple.

Resources