【问题标题】:UIWindow with wrong size when using landscape orientation使用横向时 UIWindow 大小错误
【发布时间】:2014-11-20 03:51:55
【问题描述】:

我有一个空的应用程序,没有涉及故事板或 xib。我想要一个隐藏的状态栏并且只支持横向。同样,我不想只在代码中进行这些更改,也不要触摸 Info.plist。

问题

我创建了一个带有控制器的 UIWindow,它说唯一支持的方向是横向。在这种情况下,我的 UIWindow 是在纵向模式的维度中创建的,并且不会旋转。预期的结果将是一个完全青色的屏幕。

这是我的代表:

#import "AppDelegate.h"
#import "AppViewController.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  self.window.backgroundColor = [UIColor cyanColor];
  self.window.rootViewController = [[AppViewController alloc] init];
  [self.window makeKeyAndVisible];
  return YES;
}

@end

这是我的控制器:

#import "AppViewController.h"

@implementation AppViewController

- (BOOL)shouldAutorotate {
  return YES;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
  return UIInterfaceOrientationLandscapeLeft;
}

- (BOOL)prefersStatusBarHidden {
  return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
  return UIInterfaceOrientationMaskLandscape;
}

@end

到目前为止我已经尝试过什么

如果我在调用 makeKeyAndVisible 之后设置 rootViewController,一开始一切似乎都正常。

self.window.backgroundColor = [UIColor cyanColor];
[self.window makeKeyAndVisible];
self.window.rootViewController = [[AppViewController alloc] init];

还有一些问题。首先我不喜欢这个,因为它看起来很脆弱。第二个问题是,在将 GLKViewController 设置为 rootViewController 的更复杂的应用程序中,我得到以下结果(预计左侧没有黑色区域):

看起来状态栏隐藏得不够早。几个手势识别器处于活动状态,在 GLKViewController 中单击黑色区域会产生以下日志消息:

2014-09-25 13:20:42.170 StackOverflowExample[6971:107907] 出现意外的 nil 窗口 _UIApplicationHandleEventFromQueueEvent,_windowServerHitTestWindow:UIClassicWindow:0x7fa20b805e00;帧 = (0 0; 375 667); 用户交互启用 = 否;手势识别器 = NSArray: 0x7fa20b80a620;层 = UIWindowLayer: 0x7fa20b806890

我还执行了各种其他更改,例如附加一个空的 UIViewController 并将我的视图添加为子视图。在这种情况下,我的视图看起来正确,但窗口仍然使用错误的尺寸。

如果我不覆盖视图控制器中的 supportedInterfaceOrientations 方法,一切都会正确旋转。但这当然不是我想要的。

【问题讨论】:

    标签: ios objective-c iphone landscape uiwindow


    【解决方案1】:

    当您从 portrait 模式运行 landscape 应用程序时,UIScreen 在 iOS 8 中具有 portrait 边界(仅当您的应用程序中没有此应用程序时切换面板,因为 iOS 8 做了一些缓存)。即使用makeKeyAndVisible 显示窗口也不会改变它的框架。但它会根据AppViewController 可用的方向更改[UIScreen mainScreen].bounds

    #import "AppDelegate.h"
    #import "AppViewController.h"
    
    @implementation AppDelegate
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      // Portrait bounds at this point
      self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    
      self.window.backgroundColor = [UIColor cyanColor];
      self.window.rootViewController = [[AppViewController alloc] init];
      [self.window makeKeyAndVisible];
      return YES;
    }
    
    @end
    

    所以让我们在[self.window makeKeyAndVisible]之后更改窗口的框架

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        self.window = [UIWindow new];
        self.window.backgroundColor = [UIColor cyanColor];
        self.window.rootViewController = [[AppViewController alloc] init];
        [self.window makeKeyAndVisible];
    
        // Here it is
        self.window.frame = [UIScreen mainScreen].bounds;
        return YES;
    }
    

    我认为这是 iOS 8 的错误。

    【讨论】:

    • 感谢分享。我只是花了很多时间试图弄清楚该怎么做。
    • 使用 iOS8.1 并使用 Swift 我需要在 UIWindow 的宽度和高度上添加一小部分来解决我的问题,如下所示:stackoverflow.com/a/26452679/190599
    【解决方案2】:

    我遇到了类似的问题,对于一个仅限纵向的应用程序。

    我通过在实例化 UIWindow 之前设置状态栏方向解决了这个问题

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // Init my stuff
        // ...
    
        // Prepare window
        [application setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; // prevent start orientation bug
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        [self.window makeKeyAndVisible];
        return YES;
    }
    

    在您的情况下,您应该在 setStatusBarOrientation:animated: 方法中使用 UIInterfaceOrienationLandscapeLeft(或 Right)。

    希望对你有帮助。

    【讨论】:

      【解决方案3】:

      就个人而言,上述解决方案均无效。我终于在我的主 xib 中将窗口的“隐藏”设置为 YES,正如这里首先建议的那样:unexpected nil window in _UIApplicationHandleEventFromQueueEvent, _windowServerHitTestWindow

      【讨论】:

        【解决方案4】:

        您可以通过仅添加单行来旋转 UIWindow。 你可以为你的 UIWindow 设置 rootController。例如:

        fileprivate(set) var bottonOverlayWindow = UIWindow()
        
        self.bottonOverlayWindow.rootViewController = self; 
        

        // 'self' 将是您在其上添加 UIWindow 视图的 ViewController。所以每当你 ViewController 改变方向时,你的窗口视图也会改变它的方向。

        如果您遇到任何问题,请告诉我。

        【讨论】:

          【解决方案5】:

          添加启动屏幕时问题已解决,您只能通过在 info.plist 中添加额外的属性来解决此问题

          我自己也有这个问题,我不确定你是否可以通过代码添加它,我只设法使它与 info.plist + Launch Screen xib 文件一起工作

          <key>UILaunchStoryboardName</key>
          <string>Launch Screen</string>
          

          实际上我认为您不必添加 xib 文件,如果 plist 中只有键(具有任何值)可用,它应该可以工作。

          【讨论】:

          • 很遗憾没有为我这样做。
          【解决方案6】:

          此处或其他地方发布的解决方案均不适合我。

          但是,我发现 Storyboard 显然不会出现此问题,因此另一种解决方案是远离 xibs。 (遗憾的是,这一事实也使得 Apple 不太可能认真对待这个问题。)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-12-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-05-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多