[ios] iOS 6 : 일부보기를 세로로 제한하고 다른보기는 회전하도록 허용하려면 어떻게합니까?

UINavigationController드릴 다운 인터페이스를 표시하기 위해 를 사용하는 iPhone 앱이 있습니다. 먼저 하나의보기, 다른 하나는 최대 4 단계 깊이입니다. 처음 세보기는 세로 방향으로 제한하고 마지막보기 만 가로로 회전하도록 허용해야합니다. 네 번째보기에서 세 번째보기로 돌아가고 네 번째보기는 가로 방향으로 돌아 갔을 때 모든 것이 다시 세로로 회전하기를 원합니다.

iOS 5에서는 shouldAutorotateToInterfaceOrientation:허용 가능한 방향에 대해 YES를 반환하도록 각 뷰 컨트롤러에서 간단히 정의 했습니다. 뷰 컨트롤러 # 4에서 # 3으로 돌아올 때 장치가 가로 방향으로 유지 되더라도 세로로 돌아가는 것을 포함하여 모든 것이 위에서 설명한대로 작동했습니다.

iOS 6에서는 모든 뷰 컨트롤러가 가로 방향으로 회전하여 의도하지 않은 컨트롤러를 깨뜨립니다. iOS 6 릴리스 노트에는

더 많은 책임이 앱과 앱 델리게이트로 이동하고 있습니다. 이제 iOS 컨테이너 (예 UINavigationController:)는 자동 회전 여부를 결정하기 위해 자녀에게 문의하지 않습니다. […] 시스템은 장치가 회전 할 때마다 또는 뷰 컨트롤러가 전체 화면 모달 프레젠테이션 스타일로 표시 될 때마다 지원되는 인터페이스 방향에 대해 최상위 전체 화면 뷰 컨트롤러 (일반적으로 루트 뷰 컨트롤러)에 요청합니다. 또한이 뷰 컨트롤러가 shouldAutorotate메서드 에서 YES를 반환하는 경우에만 지원되는 방향이 검색됩니다 . […] 시스템은 앱의 supportedInterfaceOrientationsForWindow:메서드에서 반환 된 값을 supportedInterfaceOrientations최상위 전체 화면 컨트롤러 의 메서드에서 반환 한 값과 교차하여 방향이 지원되는지 여부를 결정합니다 .

나는 서브 클래스 그래서 UINavigationController내 준 MainNavigationController부울 속성을 landscapeOK하고있는 허용 방향을 반환하려면이 옵션을 사용 supportedInterfaceOrientations. 그런 다음 각 뷰 컨트롤러의 viewWillAppear:메서드에 다음 과 같은 줄이 있습니다.

    [(MainNavigationController*)[self navigationController] setLandscapeOK:YES];

MainNavigationController원하는 행동 을 알려 줍니다.

여기에 질문이 있습니다. 이제 세로 모드에서 네 번째보기로 이동하고 전화기를 뒤집 으면 가로로 회전합니다. 이제 뒤로 버튼을 눌러 세로로만 작동해야하는 세 번째보기로 돌아갑니다. 그러나 그것은 뒤로 회전하지 않습니다. 그렇게하려면 어떻게해야합니까?

나는 시도했다

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait]

viewWillAppear내 세 번째 뷰 컨트롤러 의 방법에 있지만 아무것도하지 않습니다. 이것이 잘못된 호출 방법입니까, 아니면 호출하기에 잘못된 곳입니까, 아니면 완전히 다른 방식으로 전체를 구현해야합니까?



답변

나는 같은 문제가 있었고 나에게 맞는 해결책을 찾았습니다. 작동하려면 UINavigationController에서 구현 하는 것만으로 는 충분 하지 않습니다- (NSUInteger)supportedInterfaceOrientations . 또한 컨트롤러 # 3에서이 메서드를 구현해야합니다. 컨트롤러 # 4를 터뜨린 후 처음으로 세로 전용이됩니다. 그래서 내 UINavigationController에 다음 코드가 있습니다.

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if (self.isLandscapeOK) {
        // for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
        return UIInterfaceOrientationMaskAll;
    }
    return UIInterfaceOrientationMaskPortrait;
}

뷰 컨트롤러 # 3에서 다음을 추가합니다.

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

뷰 컨트롤러 # 1, # 2, # 4에 아무것도 추가 할 필요가 없습니다. 이것은 나를 위해 작동하며 도움이되기를 바랍니다.


답변

CustomNavigationController 추가

다음 메소드를 재정의하십시오.

-(BOOL)shouldAutorotate
{
    return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

이제 plist에 모든 방향을 추가하십시오.

여기에 이미지 설명 입력

보기 컨트롤러에서 필요한 것만 추가하십시오.

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

이러한 메서드는 탐색 컨트롤러 메서드를 재정의합니다.


답변

SO에 대한 수많은 유사한 질문에서 모든 답변을 살펴본 결과 어떤 답변도 저에게 효과가 없었지만 몇 가지 아이디어를 얻었습니다. 문제를 해결 한 방법은 다음과 같습니다.

먼저 프로젝트 대상에서 지원되는 인터페이스 방향에 회전 뷰에 대해 원하는 모든 방향이 포함되어 있는지 확인하십시오.

여기에 이미지 설명 입력

다음으로 카테고리를 만듭니다 UINavigationController(애플이 하위 클래스를 만들지 말라고 말했기 때문에).

@implementation UINavigationController (iOS6AutorotationFix)

-(BOOL)shouldAutorotate {
    return [self.topViewController shouldAutorotate];
}

@end

해당 카테고리와 회전 할 수있는 뷰 컨트롤러 ( RotatingViewController)를 탐색 컨트롤러를 포함해야하는 최상위 뷰 컨트롤러로 가져옵니다 . 해당 뷰 컨트롤러에서 shouldAutorotate다음과 같이 구현하십시오 . 회전하려는 뷰 컨트롤러와 동일하지 않아야합니다.

-(BOOL)shouldAutorotate {

    BOOL shouldRotate = NO;

    if ([navigationController.topViewController isMemberOfClass:[RotatingViewController class]] ) {
        shouldRotate = [navigationController.topViewController shouldAutorotate];
    }

    return shouldRotate;
}

마지막으로,에 RotatingViewController, 실행 shouldAutorotate하고 supportedInterfaceOrientations다음과 같이 :

-(BOOL)shouldAutorotate {
    // Preparations to rotate view go here
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAllButUpsideDown; // or however you want to rotate
}

이 작업을 수행해야하는 이유는 iOS 6이 상위 뷰 컨트롤러 대신 루트 뷰 컨트롤러에 회전 제어를 제공하기 때문입니다. 개별 뷰의 회전이 스택의 다른 뷰와 다르게 동작하도록하려면 루트 뷰 컨트롤러에서 특정 사례를 작성해야합니다.


답변

@Brian의 답변에 대해 언급 할만한 평판이 충분하지 않으므로 여기에 메모를 추가하겠습니다.

Brian은 iOS6가 rootViewController에 회전 제어를 제공한다고 언급했습니다. 이것은 언급 한대로 UINavigationController 일 수있을뿐만 아니라 저를위한 UITabBarController 일 수도 있습니다. 내 구조는 다음과 같습니다.

  • UITabBarController
    • UINavigationController
      • UIViewControllers …
    • UINavigationController
      • UIViewControllers …

그래서 먼저 사용자 지정 UITabBarController에 메서드를 추가 한 다음 사용자 지정 UINavigationController에, 마지막으로 특정 UIViewController에 메서드를 추가했습니다.

UITabBarController 및 UINavigationController의 예 :

- (BOOL)shouldAutorotate {
    return [self.viewControllers.lastObject shouldAutorotate];
}

- (NSUInteger)supportedInterfaceOrientations {
    return [self.viewControllers.lastObject supportedInterfaceOrientations];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return [self.viewControllers.lastObject shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return [self.viewControllers.lastObject preferredInterfaceOrientationForPresentation];
}


답변

내 질문에 부분적으로 대답하고 싶습니다. viewWillAppear세 번째 방법 에서 사용되는 다음 코드 줄이 작동하는 것을 발견 UIViewController했습니다.

[[UIDevice currentDevice]
      performSelector:NSSelectorFromString(@"setOrientation:")
           withObject:(id)UIInterfaceOrientationPortrait];

하지만 저는이 솔루션이 마음에 들지 않습니다. Apple 문서 에 따라 장치 의 물리적 방향을 나타내는 읽기 전용 속성에 할당하는 트릭을 사용하고 있습니다. 사용자의 손에서 올바른 방향으로 이동하도록 iPhone에 지시하는 것과 같습니다.

나는 단순히 작동하기 때문에 이것을 내 앱에 남겨두고 싶었습니다. 그러나 그것은 옳지 않다고 생각하기 때문에 깨끗한 해결책을 위해 질문을 열어두고 싶습니다.


답변

이것은 iOS 6.0에서 방향 지원을 위해 사용하고 있습니다.

-(BOOL)shouldAutorotate{
    return YES;
}

 - (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskAll;
}


- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
  return UIInterfaceOrientationPortrait;
}


답변

이것은 높은 평가 스레드이기 때문에. 가장 쉬운 답이라고 생각하는 것을 추가하겠다고 생각했습니다. 이것은 ios8 이상에서 작동합니다.

-(BOOL)shouldAutorotate
{
    return YES;
}

-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}

그게 다야. 즐겨!

아, 그리고 내 ViewController는 탐색 컨트롤러에 포함되어 있으므로 어떤 식 으로든 하위 클래스를 지정하거나 구성 할 필요가 없습니다.