2
votes

I have one app always presenting in Portrait mode (in the summary of the Xcode project, only the portrait orientation is supported).

Now what I want to do is when I'm using the app, from any view controllers of the app, if I rotate the device in landscape right, the app presents a view controller (ARViewController.m) in landscape right, in fact the rotation to landscape right is the trigger to present ARViewController.m. But what I've experienced is, since the the first view controller only supports portrait and even if I orient the device in landscape right, the view controller (ARViewController.m) I want to present from the first one is in portrait too, not in landscape right.

Even if I write this in the second view controller (ARViewController.m), it doesn't autorotate (this view controller can be presented in every orientations):

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{ 
  return YES;
}

I have to rotate the iphone once after the second view controller (ARViewController.m) is presented to have all in order.

And here is how I call this second view controller (ARViewController.m) from the first view controller:

ARViewController *arVC = [[ARViewController alloc] initWithNibName:@"ARViewController" bundle:nil];
[self presentModalViewController:arVC animated:YES];

I'm calling it from "ViewController.m", this one is defined as the rootViewController in the AppDelegate.m.

This is the first time I'm doing such things, I've looked for solutions but still the same problem. Any tips on this?

2

2 Answers

5
votes

I finally solved this problem, I suppose there are alternatives but this one works fine:

In fact I kept only Portrait in the orientation restrictions. Then when I turn the phone in landscape right or left, I call my ARViewController modally, but before loading it I force this view controller to landscape (in viewWillAppear) by making an appropriate rotation like here:

- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self transformView2ToLandscape];}

-(void) transformView2ToLandscape {

NSInteger rotationDirection;
UIDeviceOrientation currentOrientation = [[UIDevice currentDevice] orientation];

if(currentOrientation == UIDeviceOrientationLandscapeLeft){
    rotationDirection = 1;
}else {
    rotationDirection = -1;
}

CGAffineTransform transform = [arController.viewController.view transform];
transform = CGAffineTransformRotate(transform, degreesToRadians(rotationDirection * 90));
[arController.viewController.view setTransform: transform];}

Edit: In Swift 4

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    transformViewToLansdcape()
}

func transformViewToLansdcape(){
    var rotationDir : Int
    if(UIDeviceOrientationIsLandscape(UIDevice.current.orientation)){
        rotationDir = 1
    }else{
        rotationDir = -1
    }
    var transform = self.view.transform
    //90 for landscapeLeft and 270 for landscapeRight
    transform = transform.rotated(by: (rotationDir*270).degreesToRadians)
    self.view.transform = transform
}

extension BinaryInteger {
    var degreesToRadians: CGFloat {
        return CGFloat(Int(self)) * .pi / 180
    }
}
0
votes

What i've found is that first of all, what's stopping the entire application from rotating is the project summary sheet. What you should do is deselect the restrictions in the project summary sheet & just put a method in each UIViewController like you'd like it to be. In the UIViewController that you have, make the method available for the landscape orientations & implement the method

[UIViewControllerSubclass willRotateToInterfaceOrientation:<interfaceOrientation> duration:<NSTimeInterval>]

what Apple says:

willRotateToInterfaceOrientation:duration:

Sent to the view controller just before the user interface begins rotating.

  • (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

Parameters

toInterfaceOrientation

The new orientation for the user interface. The possible values are described in UIInterfaceOrientation.

duration

The duration of the pending rotation, measured in seconds.

Discussion

Subclasses may override this method to perform additional actions immediately prior to the rotation. For example, you might use this method to disable view interactions, stop media playback, or temporarily turn off expensive drawing or live updates. You might also use it to swap the current view for one that reflects the new interface orientation. When this method is called, the interfaceOrientation property still contains the view’s original orientation.

This method is called regardless of whether your code performs one-step or two-step rotations.


so, this seems like the method you are looking for. Just implement this, and put your view calling code inside & it should work. (also, put one of these in the presented view to return when rotated back)

also, you should consider not presenting the view controller modally as it is rotating anyways and is obvious that the display is changing.