报告横向模式中的错误边界

时间:2011-03-04 13:43:40

标签: iphone objective-c cocoa-touch uikit

我在iPad应用程序中遇到横向模式问题。

我创建了一个非常小的新项目来展示我的问题 我将pList中的UIInterfaceOrientation设置为UIInterfaceOrientationLandscapeRight

在app delegate中

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    [self.window makeKeyAndVisible];
    MyController *myController = [[MyController alloc] init];
    [self.window addSubview:myController.view];

    return YES;
}

在MyController中

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    NSLog(@"Bounds Height:%f %f", self.view.bounds.size.height, self.view.bounds.size.width);
}

我也试过把它放在viewDidLoad中,结果相同

如果我在横向握住设备的同时启动应用程序NSLog输出

Bounds Height: 1004.000000 Bounds Width: 768.000000

我需要做些什么才能获得正确的结果? 我是这个iOS编程的新手,我想要做的就是将UISlider锚定到屏幕的底部但是当我得到不正确的坐标时,我不确定该怎么做。

9 个答案:

答案 0 :(得分:58)

我不认为原来的问题在这里得到了回答,因为我遇到了同样的问题。

这里的关键是,如果模拟器/设备处于横向模式,然后启动程序,则self.view。(框架或边界)将检索纵向高度和宽度。如果您的程序已在运行,然后您旋转它会给出正确的值。仅当设备在横向启动且未旋转时才会出现此情况。

有没有其他人找到解决方案或知道我做错了什么?请&谢谢。

可能的解决方案

我之前从viewDidLoad方法调用了我的方法。事实证明,视图仍在转变。通过从一切完成后调用的viewDidAppear调用我的函数,我运气更好。

希望有所帮助。

答案 1 :(得分:12)

你过早检查框架和边界大小。

相反,请在轮换后检查它们:

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

(注意我使用NSStringFromCGRect - 方便!)

这会产生输出:

Bounds {{0, 0}, {1024, 748}}
Frame {{0, 0}, {748, 1024}}

所以在这个输出中框架是“错误的”,但边界是你所期望的。事实上,框架实际上并没有错,那就是框架 - >边界计算发生了。所以你需要访问边界。

另见Do I have the right understanding of frames and bounds in UIKit?

N.B。在事物计划中,viewDidAppear会比你想象的更早被调用。根据Apple文档:“viewDidAppear通知视图控制器其视图已添加到窗口中。”换句话说,它可以在应用任何旋转之前发生。

答案 2 :(得分:10)

我遇到了同样的问题并且像这样被黑了:

- (CGSize)getRotatedViewSize
{
    BOOL isPortrait = UIInterfaceOrientationIsPortrait(self.interfaceOrientation);

    float max = MAX(self.view.bounds.size.width, self.view.bounds.size.height);
    float min = MIN(self.view.bounds.size.width, self.view.bounds.size.height);

    return (isPortrait ? 
            CGSizeMake(min, max) : 
            CGSizeMake(max, min));            
}

答案 3 :(得分:2)

viewWillAppear(根据Paul Hegarty的CS193p讲座)用于几何相关的初始化。由于viewDidAppear跟随viewWillAppear,因此这里的边界也是正确的。视图边界尚未在viewDidLoad中设置。

答案 4 :(得分:2)

viewDidAppear:外,请确保使用_window.rootViewController代替[_window addSubview:_rootViewController.view]。这也解决了我在iOS6上的问题。

AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
  _window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  _rootViewController = [[MyRootViewController alloc] init];
  _window.rootViewController = _rootViewController;
  [_window makeKeyAndVisible];
  return YES;
}

MyRootViewController.m:

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  NSLog(@"bounds: %@", NSStringFromCGRect(self.view.bounds));
  UIView *myView = [[UIView alloc] initWithFrame:self.view.bounds];
  [self.view addSubview:myView];
}

答案 5 :(得分:1)

我创建了一个小项目来测试帧和边界,因为我遇到了同样的问题。 事实上,检查viewDidLoad上的边界解决了我的问题。

我一直在挖掘,我发现viewWillLayoutSubviews方法的边界也是正确的。所以我想在项目中布置视图的最“正确”的方法是:

  1. 在viewDidLoad或loadView上使用您认为当时正确的帧来分配和实例化它们。

  2. 在viewWillLayoutSubviews上重新布局您创建的视图,以便在视图实际显示时它们位于正确的位置。

答案 6 :(得分:1)

对接受的答案的评论之一包含了解决问题的方法。

你可以在UIViewController上覆盖一个名为" viewDidLayoutSubviews"的方法,我点击它并从那里调整我的包含视图。

并且自从它被称为" viewWillAppear"之前" viewDidAppear"您对子视图所做的更改会按预期显示,没有任何故障。

答案 7 :(得分:0)

我发生了同样的事情。

你必须用勺子喂iOS并在这里放置这行代码,否则它会给你错误的答案。

-(void) viewWillAppear:(BOOL)animated
{
  [super viewWillAppear:animated];
  //required because device orientation will give you the wrong values
  [UIViewController attemptRotationToDeviceOrientation];
  int orientation = [[UIDevice currentDevice] orientation];
  BOOL isPortrait = false;

  if (orientation == 3 || orientation == 4)
    isPortrait = false;
  else
    isPortrait = true;
  NSLog(@"is portrait %i ?", isPortrait);
}

答案 8 :(得分:0)

UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect r = self.view.frame;
CGFloat width = r.size.width;
CGFloat height = r.size.height;
r.size.height = (UIInterfaceOrientationIsLandscape(orientation)) ? MIN(width, height): MAX(width, height);
r.size.width  = (UIInterfaceOrientationIsLandscape(orientation)) ? MAX(width, height): MIN(width, height);
self.view.frame = r;