iOS8에서 [UIWindow new]에서 생성한 Window의 frame 원점이 Landscape 상태의 화면에도 불구하고 Portrait 좌상이 되어 버리는 현상을 해결했다

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] 에서 윈도우 생성
  • 생성된 윈도우는 [vc shouldAutorotate] == NO 이 된다 ViewController
  • 생성 된 윈도우의 rootViewController를 전체 화면으로 만들려고합니다. frame
  • Landscape 상태에서 윈도우 생성 및 표시

  • 다음은 요점을 추출한 코드.
    // 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
    

    이것이





    이렇게





    iOS 8만 ​​UIScreen의 원점과 생성한 Window의 원점이 다르다.
  • UIScreen은 보이는 화면의 왼쪽 상단을 원점으로합니다
  • [UIScreen mainScreen].bounds 에 의해 생성된 [UIWindow new]UIWindow 상태의 왼쪽 위를 원점으로 합니다.

    HACK로 해결


    Portrait 하지만 shouldAutoRotate UIViewController를 갖게 한 다음 YES 라고 하는 발상 아래, 이하와 같이 한 곳 잘 갔다.
    - (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할 수밖에 없는 것인가… 라고 하는 고민으로부터 해결되어 최고로 기분이 좋다.

  • swift - iOS 8 - UIWindow Orientation Is Always Portrait - Stack Overflow
  • 읽을 때 별개일까라고 생각했지만, 해결한 지금, 분명히 이 추기가 베스트인 대답이라고 이해했다

  • 좋은 웹페이지 즐겨찾기