简体   繁体   中英

UIViewController/UIView orientation frame/bounds in landscape only app

There are a few questions already on this, but none with a satisfactory answer. I'd like to know exactly why the frame and bounds appear to be wrong, using the simplest possible example, and for someone to tell me what the proper way to deal with it is...

I make a single view application, without a storyboard, and i tick support for landscape only. Then in didFinishLaunching method:


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    ViewController *vc = [[ViewController alloc] init];
    self.window.rootViewController = vc;
    [self.window makeKeyAndVisible];

    return YES;
}

and in the view controller:


- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
}

- (void)viewDidAppear:(BOOL)animated
{
    NSLog(@"%.1f,%.1f",self.view.frame.size.width,self.view.frame.size.height);
}

Then the output is 768.0,1024.0 - which is obviously wrong, even though the red color has filled the landscape size screen. So I can't rely on the self.view.frame or self.view.bounds to arrange or resize subviews.

What is the most up to date and "proper" way to avoid problems like this? (without using nibs or storyboards, and without hacky swapping of width and height)

Not sure if this is right, but it's my best guess and I'm unable to test at this moment. If I'm not mistaking, the default orientation is portrait for any application. So, in order to support different orientations, your application should implement the auto rotation methods (are a bit different depending on the iOS version you're building on). So even if you application is ticked to only support landscape mode, it never actually rotates. Try implementing the specified methods and let me know how it goes...

for iOS 5 and earlier you should use:

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
return YES;
}

return NO;
}

for iOS 6 and later you should use:

-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}

-(BOOL)shouldAutorotate
{
return YES;
}

If you check the view's frame after the rotation takes place, it should be allright.

EDIT:

Take a look at this SO question and it's answers. They provide some nice workarounds. Also, given that in an application you will mostly have your view controllers embedded in a navigation controller or tab bar controller or even both, you can go ahead and subclass/create category on them to make sure that everything is forwarded to your view controllers.

Another great answer explains what's actually happening.

You're checking the frame and bounds size too soon.

Instead, check them after rotation:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    NSLog(@"Bounds %@", NSStringFromCGRect(self.view.bounds));
    NSLog(@"Frame %@", NSStringFromCGRect(self.view.frame));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM