LoginSignup
1
1

More than 5 years have passed since last update.

iOS8にて、[UIWindow new]で生成したWindowのframe原点が、Landscape状態の画面にも関わらず、Portrait左上になってしまう現象を解決した

Last updated at Posted at 2017-08-04

iOS 8からframeなど座標を考える上で、スクリーン上で見えているOrientationの左上が原点となるようになった。
月日は流れiOS 11も出る頃なので、いい加減切りたいバージョンも増えつつある今日このごろ、
[UIWindow new]を使用するにあたって、iOS 8系でのみ発生する不具合のような挙動に直面した。

多分Swiftでも起こるのでタグ付けした。

何が起こるか

iOS 8でだけ、UIWindowを生成して表示したとき、Landscape表示しているにも関わらずPortraitで表示される。

どういう状況で起こるか

  • iOS 8.xである(iOS 7.x以下、iOS 9.x以上では発生しない)
  • [UIWindow new]でWindowを生成する
  • 生成したWindowは[vc shouldAutorotate] == NOとなるViewControllerrootViewControllerに持つ
  • 生成したWindowのframeをフルスクリーンにしようと[UIScreen mainScreen].boundsの値を使う
  • Landscape状態でWindowを生成・表示する

以下は要点を抽出したコード。

// SampleViewController.h
@interface SampleViewController : UIViewController
@end
// SampleViewController.m
@implementation SampleViewController
- (BOOL)shouldAutoRotate {
    return NO;
}
@end
// ViewController.m
@interface ViewController ()
@property (nonatomic) UIWindow *w;
@end

@implementation ViewController
- (IBACtion)openWindow:(UIButton*)sender {
    UIWindow *w = [UIWindow new];
    w.frame = [UIScreen mainScreen].bounds;
    w.rootViewController = [SampleViewController new];

    self.w = w;
    [self.w makeKeyAndVisible];
}
@end

これが

Simulator Screen Shot 2017.08.04 11.50.52.png

こうなる

screenshot.png

iOS 8だけ、UIScreenの原点と生成したWindowの原点が異なっている。

  • UIScreenは見えているスクリーンの左上を原点としている
  • [UIWindow new]によって生成されたUIWindowPortrait状態の左上を原点としている

HACKに解決

shouldAutoRotateYESなUIViewControllerを持たせた上でmakeKeyAndVisibleかけたら上手くいくんじゃね?という発想のもと、以下のようにしたところ上手くいった。

- (IBACtion)openWindow:(UIButton*)sender {
    UIWindow *w = [UIWindow new];
    w.frame = [UIScreen mainScreen].bounds;

    // HACK: iOS 8系にてShouldAutoRotate == NO のViewControllerを
    //       rootViewControllerに持ってmakeKeyAndVisibleを実行すると
    //       アプリケーションのInterfaceOrientationに関わらず
    //       InterfaceOrientationPortrait状態のWindowが表示されてしまう
    //       iOS 9以降では空のUIViewControllerを持たせる必要はなく、
    //       表示したいViewControllerを持たせて構わない
    w.rootViewController = [UIViewController];

    self.w = w;
    [self.w makeKeyAndVisible];

    // HACK: iOS 8系にてShouldAutoRotate == NO のViewControllerを
    //       rootViewControllerに持ってmakeKeyAndVisibleを実行すると
    //       アプリケーションのInterfaceOrientationに関わらず
    //       InterfaceOrientationPortrait状態のWindowが表示されてしまう
    //       よって空のViewControllerを持たせてmakeKeyAndVisibleを実行した後に
    //       ViewControllerを差し替える
    w.rootViewController = [SampleViewController new];
}

直前まで表示されていたWindowのInterfaceOrientationを元に、表示したいWindowにtransformかけるしかないのか…?という悩みから解決されて最高に気分がいい。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1