4
\$\begingroup\$

I got the solution for the question asked here, but I don't like how the code is written.

This part of the code rotates the screen if it's in landscape and sets the size to match the screen. I don't like the if and the 7x else if. Can you suggest something more readable? Something like (appOrientation - fromInterfaceOrientation) == 2 than angle (M_PI / 2.0)?

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{ 

    UIInterfaceOrientation appOrientation = [UIApplication sharedApplication].statusBarOrientation;
    float width = self.view.bounds.size.width;
    float height = self.view.bounds.size.height;
    //NSLog(@"width %3.0f, height: %3.0f", width, height);

//    UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,
//    UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
//    UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
//    UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft

    CGFloat angle = 0;

    // rotate from Portait
    if((fromInterfaceOrientation == UIInterfaceOrientationPortrait) && (appOrientation == UIInterfaceOrientationLandscapeLeft)){
        angle = -(M_PI / 2.0);
    }
    else if((fromInterfaceOrientation == UIInterfaceOrientationPortrait) && (appOrientation == UIInterfaceOrientationLandscapeRight)){
        angle = (M_PI / 2.0);
    }    
    // rotate from PortraitUpsideDown
    else if((fromInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) && (appOrientation == UIInterfaceOrientationLandscapeLeft)){
        angle = (M_PI / 2.0);
    }
    else if((fromInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) && (appOrientation == UIInterfaceOrientationLandscapeRight)){
        angle = -(M_PI / 2.0);
    }


    //rotate from Landscape:
    else if((fromInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) && (appOrientation == UIInterfaceOrientationPortrait)){
        // search for exactly the inverse...
    }
    // must be something more elgant code


    CGAffineTransform transform = self.view.transform;
    transform = CGAffineTransformRotate(transform, angle);
    self.view.transform = transform;            

    [self.view setBounds:CGRectMake(0, 0, height, width)];
\$\endgroup\$
0

2 Answers 2

1
\$\begingroup\$

I think that you can rewrite the code in a more OO way, with the help of an NSDictionary and setting up a sort of command pattern.

You can store a sum of the two enumerator value as a key of the Dictionary in this way :

NSDictionary *dicAngles = [[NSDictionary alloc] initWithObjectsAndKeys: 
        (UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft), -(M_PI / 2.0),     (UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeRight), (M_PI / 2.0), 
(UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft), (M_PI / 2.0), 
(UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeRight), -(M_PI / 2.0),
 nil];

Once you have the dictionary you can avoid the if - else control flow in this way :

 CGFloat angle = 0;
 //Retrieve the angle from the dictionary 
 angle = [dicAngles objectForKey: ( fromInterfaceOrientation + appOrientation )];

It is only an example and not tested, but could be a more elegant solution i think ...

\$\endgroup\$
3
  • \$\begingroup\$ How are you storing using a float as a key - an NSDictionary requires an object that implements NSCopying which I'm pretty sure a float doesn't! \$\endgroup\$ Sep 10, 2012 at 14:10
  • \$\begingroup\$ You can wrap it in an Object, it's only an untested example as stated in the answer, but could give an idea of a possible way to avoid the if ... \$\endgroup\$
    – aleroot
    Sep 10, 2012 at 14:13
  • \$\begingroup\$ This is very error-prone solution. Not readable at all. \$\endgroup\$
    – Sulthan
    Sep 11, 2012 at 9:00
1
\$\begingroup\$
//Angle of every orientation
double orientationAngles[] = {
   orientationAngles[UIDeviceOrientationPortrait] = 0.0,
   orientationAngles[UIDeviceOrientationLandscapeLeft] = (M_PI / 2.0),
   orientationAngles[UIDeviceOrientationPortraitUpsideDown] = M_PI,
   orientationAngles[UIDeviceOrientationLandscapeRight] = -(M_PI / 2.0)
};

//What you want is the difference between adjancent angles
double angle = orientationAngles[fromInterfaceOrientation] - orientationAngles[appOrientation];

//Putting the result into the requested interval
if (angle > M_PI / 2) {
   angle -= 2 * M_PI;
}
else if (angle < - M_PI / 2) {
   angle += 2 * M_PI;
}

Another possible solution, less math, more ifs.

UIDeviceOrientation orientations[] = {
  UIDeviceOrientationPortrait,
  UIDeviceOrientationLandscapeLeft,
  UIDeviceOrientationPortraitUpsideDown,
  UIDeviceOrientationLandscapeRight,
};

for (int i = 0; i < 4; i++) {
   //UIDeviceOrientation previous = (i == 0) ? orientations[3] : orientations[i - 1];
   UIDeviceOrientation next = (i == 3) ? orientations[0] : orientations[i + 1];
   UIDeviceOrientation current = orientations[i];

   if (current == appOrientation) {
      if (fromInterfaceOrientation == next) {
         angle = (M_PI / 2.0);
      }
      else { //(fromInterfaceOrientation == previous)
         angle = -(M_PI / 2.0);
      }

      break;
   }
}

As you can see, both solutions are using an array to hold the sequence of orientations. If you know the possible transitions, everything else is simple.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.