iOS 8에서 뷰 컨트롤러 방향을 강제하는 방법은 무엇입니까?


149

iOS 8 이전에는 supportedInterfaceOrientations shouldAutoRotate 대리자 메서드 하여 앱 방향을 특정 방향으로 강제했습니다. 아래 코드 스 니펫을 사용하여 응용 프로그램을 원하는 방향으로 프로그래밍 방식으로 회전했습니다. 먼저 상태 표시 줄 방향을 변경하고 있습니다. 그런 다음 모달 뷰를 제시하고 즉시 닫으면 뷰가 원하는 방향으로 회전합니다.

[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];
UIViewController *c = [[UIViewController alloc]init];
[self presentViewController:vc animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];

그러나 이것은 iOS 8에서 실패합니다. 또한 사람들이 iOS 8부터는이 접근법을 항상 피해야한다고 제안한 스택 오버플로에 대한 답변을 보았습니다.

좀 더 구체적으로 말하면, 내 응용 프로그램은 범용 유형의 응용 프로그램입니다. 총 3 개의 컨트롤러가 있습니다.

  1. 퍼스트 뷰 컨트롤러 -iPad에서는 모든 방향을 지원하고 iPhone에서는 세로 (홈 버튼 아래로) 만 지원해야합니다.

  2. Second View 컨트롤러 -모든 조건에서 가로 만 지원해야합니다.

  3. Third View 컨트롤러 -모든 조건에서 가로 만 지원해야합니다.

페이지 탐색을 위해 탐색 컨트롤러를 사용하고 있습니다. 첫 번째 뷰 컨트롤러에서 버튼 클릭 동작으로 두 번째 뷰 컨트롤러를 스택에 밀어 넣습니다. 따라서 장치 방향에 관계없이 두 번째 뷰 컨트롤러가 도착하면 앱은 가로 방향으로 만 잠 가야합니다.

다음은 내 것입니다 shouldAutorotatesupportedInterfaceOrientations두 번째와 세 번째 뷰 컨트롤러의 방법.

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscapeRight;
}

-(BOOL)shouldAutorotate {
    return NO;
}

iOS 8의 경우 특정 방향으로 뷰 컨트롤러를 잠그는 더 좋은 방법이 있습니까? 도와주세요 !!


제시된 VC 에서 언급 한 방법을 구현하면 일반적으로 작동해야합니다 (적어도 iOS 8에서 저의 경험입니다). 특정 설정으로 인해 문제가 발생했을 수 있습니다.
Vladimir Gritsenko

질문을 조금 더 명확하게 만들 수 있을까요? 질문을 약간 편집하겠습니다.
Rashmi Ranjan mallick

@VladimirGritsenko : 지금 확인하십시오. 편집했습니다.
Rashmi Ranjan mallick

문제의 코드는 탐색 컨트롤러의 스택을 사용하지 않고 모달 프레젠테이션을 사용하므로 정확히 무엇을하고 있는지 명확하지 않습니다. 코드에서 shouldAutoRotate에서 YES를 반환하고 표시된 VC의 supportedInterfaceOrientations에서 원하는 방향을 반환하면 해당 VC의 방향이 올바르게 설정됩니다.
Vladimir Gritsenko

글쎄, 그것은 실제로 실패가 아니며 개념의 큰 변화 일뿐입니다. 좋은 변화인지 여부는 전적으로 다른 주제입니다.
Kegluneq

답변:


315

iOS 7-10의 경우 :

목표 -C :

[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeLeft) forKey:@"orientation"];
[UINavigationController attemptRotationToDeviceOrientation];

스위프트 3 :

let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
UINavigationController.attemptRotationToDeviceOrientation()

- viewDidAppear:제시된 뷰 컨트롤러 에서 호출하면됩니다 .


61
이것은 비공개 API 가 아닙니다 . 이것은 안전하지 않은 API 사용입니다. 개인 방법을 사용하지 않고 '내부 사물'을 사용하고 있습니다. Apple이 "방향"값을 변경하면 실패합니다. 더 나쁜 점 : Apple이 "동향"값의 의미를 변경하면, 값을 변경하는 값이 무엇인지 알 수 없습니다.
sonxurxo

4
넣어 사용하지 않도록 애니메이션에 [UIView setAnimationsEnabled:NO];에서 viewWillAppear[UIView setAnimationsEnabled:YES];에서 viewDidAppear: 관련, stackoverflow.com/a/6292506/88597
ohho

3
좋은 해킹이지만 그 문제는 새로운 방향 값 (한숨)을 설정 한 후 didRotateFromInterfaceOrientation을 실행하지 않는 것입니다.
loretoparisi

2
iOS 9.2에서는 방향이 바뀌지 만 잠기지 않습니다.
Mark13426

2
이것을 가진 모든 사람이 시간의 90 %를 잘 행동하고 시간의 다른 10 %를 버기하려면 오리엔테이션 키를 설정 한 후 이것을 호출하십시오.[UINavigationController attemptRotationToDeviceOrientation];
Albert Renshaw

93

방향 회전은 내부 UINavigationController또는 내부에 있으면 조금 더 복잡합니다.UITabBarController . 문제는 뷰 컨트롤러가 이러한 컨트롤러 중 하나에 내장 된 경우 내비게이션 또는 탭 막대 컨트롤러가 우선하고 자동 회전 및 지원되는 방향을 결정한다는 것입니다.

UINavigationController 및 UITabBarController에서 다음 두 가지 확장을 사용하여 이러한 컨트롤러 중 하나에 포함 된 뷰 컨트롤러가 결정을 내릴 수 있습니다.

View Controller에 전원을 공급하십시오!

스위프트 2.3

extension UINavigationController {
    public override func supportedInterfaceOrientations() -> Int {
        return visibleViewController.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        return visibleViewController.shouldAutorotate()
    }
}

extension UITabBarController {
    public override func supportedInterfaceOrientations() -> Int {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations()
        }
        return super.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate()
        }
        return super.shouldAutorotate()
    }
}

스위프트 3

extension UINavigationController {
    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return visibleViewController?.supportedInterfaceOrientations ?? super.supportedInterfaceOrientations
    }

    open override var shouldAutorotate: Bool {
        return visibleViewController?.shouldAutorotate ?? super.shouldAutorotate
    }
}

extension UITabBarController {
    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations
        }
        return super.supportedInterfaceOrientations
    }

    open override var shouldAutorotate: Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate
        }
        return super.shouldAutorotate
    }
}

이제 supportedInterfaceOrientations메서드를 재정의하거나 재정의 할 수 있습니다shouldAutoRotate 잠 그려는보기 컨트롤러에서 . 그렇지 않으면 앱의 plist에 지정된 기본 방향 동작을 상속하려는 다른보기 컨트롤러에서 재정의를 생략 할 수 있습니다

회전 비활성화

class ViewController: UIViewController {
    override func shouldAutorotate() -> Bool {
        return false
    }
}

특정 방향으로 고정

class ViewController: UIViewController {
    override func supportedInterfaceOrientations() -> Int {
        return Int(UIInterfaceOrientationMask.Landscape.rawValue)
    }
}

이론적으로 이것은 모든 복잡한보기 컨트롤러 계층 구조에서 작동하지만 UITabBarController에 문제가 있음을 알았습니다. 어떤 이유로 기본 방향 값을 사용하려고합니다. 일부 문제를 해결하는 방법에 대해 배우려면 다음 블로그 게시물을 참조하십시오.

잠금 화면 회전


1
나는 이것이 매우 오래된 게시물이라는 것을 알고 있지만 확장 코드를 어디에 넣을 것인가?
dwinnbrown

7
Swift의 다운 마킹은 Objective-C 질문에 대해서만 답변합니다.
Charlie Scott-Skinner

17
이것은 Swift와 ObjC를위한 훌륭한 솔루션입니다. 사람들이 왜 투표를 거부하는지 이해하지 못합니다. 아이디어를 얻은 다음 코드를 작성하는 것은 쉽습니다. 왜 불평합니까?
Zhao

2
@Krodak, 확장에서 "-> Int"를 "-> UIInterfaceOrientationMask"로 변경하십시오. 나를 위해 트릭을 했어.
the_pantless_coder

2
아이디어와 코드는 완벽합니다. 마음에 들지만 UINavigationController를 사용하고 가로로 표시된 UIViewController에서 세로로 표시 해야하는 UIViewController로 돌아갈 때 문제가 있습니다. 어떤 아이디어?
crisisGriega

24

이것이 나를 위해 일한 것입니다.

https://developer.apple.com/library//ios/documentation/UIKit/Reference/UIViewController_Class/index.html#//apple_ref/occ/clm/UIViewController/attemptRotationToDeviceOrientation

viewDidAppear : 메소드에서 호출하십시오.

- (void) viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    [UIViewController attemptRotationToDeviceOrientation];
}

3
매우 유용한 장치가 이미 회전 당신은 당신의 뷰 컨트롤러를 회전해야하는 경우
avdyushin

2
좋은 대답입니다. 허용 된 답변과 함께 사용하면 Swift 및 iOS 9 이상에서 항상 잘 작동합니다.
AndyDunn

1
나는 그것이 질문에 대한 대답이 아니라고 생각하지만 실제로 도움이되었습니다.
Abdurrahman Mubeen Ali

21

제공된보기 컨트롤러 인 경우 무시할 수 있음을 발견했습니다. preferredInterfaceOrientationForPresentation

빠른:

override func supportedInterfaceOrientations() -> Int {
  return Int(UIInterfaceOrientationMask.Landscape.rawValue)
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
  return UIInterfaceOrientation.LandscapeLeft
}

override func shouldAutorotate() -> Bool {
  return false
}

4
허용 된 답변은 단순히 방향을 가로 방향으로 변경하는 것으로 보입니다. 당신이 여기에 표시 한 것은하는 방법은 강제 에보기 컨트롤러 (정확히 내가 필요하다)을 제시 뷰 컨트롤러에 영향을 미칠 풍경, 그리고 없습니다. 감사.
Clifton Labrum

1
@CliftonLabrum 풍경 강요하기 위해 다른 작업을 했습니까? 동일한 코드를 사용하여 뷰 컨트롤러는 여전히 다른 방향으로 회전 할 수 있습니다.
Crashalot

나는 나중에 당신이 옳다는 것을 깨달았습니다. 아직 해결책을 찾지 못했습니다.
Clifton Labrum

1
이것은 나를 위해 일했습니다. 이 코드를 사용하여 세로 모드에서 단일 View Controller를 유지할 수있었습니다 (가로 가로 바꾸기). +1
Mark Barrasso

예! 이것은 Xcode 7.3 & Swift 2.2에서도 나에게 효과적이었습니다. 그러나 여전히 AppDelegate에서 supportedInterfaceOrientationsForWindow에 대한 func 응용 프로그램을 정의해야합니다.
charles.cc.hsu

15

이 방법은 Swift 2 iOS 8.x 에서 작동합니다 .

추신 (이 방법은 모든 viewController에서 자동 회전 해야하는 방향 함수를 재정의 할 필요가 없으며 AppDelegate에서 단 하나의 방법)

프로젝트 일반 정보에서 "전체 화면 필요"를 확인하십시오. 여기에 이미지 설명을 입력하십시오

따라서 AppDelegate.swift에서 변수를 만드십시오.

var enableAllOrientation = false

따라서이 기능을 넣으십시오.

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
        if (enableAllOrientation == true){
            return UIInterfaceOrientationMask.All
        }
        return UIInterfaceOrientationMask.Portrait
}

따라서 프로젝트의 모든 클래스에서 viewWillAppear에서이 변수를 설정할 수 있습니다.

override func viewWillAppear(animated: Bool)
{
        super.viewWillAppear(animated)
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        appDelegate.enableAllOrientation = true
}

장치 유형에 따라 선택해야하는 경우 다음을 수행 할 수 있습니다.

override func viewWillAppear(animated: Bool)
    {
        super.viewWillAppear(animated)
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        switch UIDevice.currentDevice().userInterfaceIdiom {
        case .Phone:
        // It's an iPhone
           print(" - Only portrait mode to iPhone")
           appDelegate.enableAllOrientation = false
        case .Pad:
        // It's an iPad
           print(" - All orientation mode enabled on iPad")
           appDelegate.enableAllOrientation = true
        case .Unspecified:
        // Uh, oh! What could it be?
           appDelegate.enableAllOrientation = false
        }
    }

아주 좋은 설명
Mihir Oza

11

우선, 이것은 일반적으로 나쁜 생각입니다. 앱 아키텍처에 문제가 있지만, sh..t happens그렇다면 다음과 같이 만들 수 있습니다.

final class OrientationController {

    static private (set) var allowedOrientation:UIInterfaceOrientationMask = [.all]

    // MARK: - Public

    class func lockOrientation(_ orientationIdiom: UIInterfaceOrientationMask) {
        OrientationController.allowedOrientation = [orientationIdiom]
    }

    class func forceLockOrientation(_ orientation: UIInterfaceOrientation) {
        var mask:UIInterfaceOrientationMask = []
        switch orientation {
            case .unknown:
                mask = [.all]
            case .portrait:
                mask = [.portrait]
            case .portraitUpsideDown:
                mask = [.portraitUpsideDown]
            case .landscapeLeft:
                mask = [.landscapeLeft]
            case .landscapeRight:
                mask = [.landscapeRight]
        }

        OrientationController.lockOrientation(mask)

        UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
    }
}

보다 AppDelegate

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // do stuff
    OrientationController.lockOrientation(.portrait)
    return true
}

// MARK: - Orientation

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return OrientationController.allowedOrientation
}

방향을 변경할 때마다 다음과 같이하십시오.

OrientationController.forceLockOrientation(.landscapeRight)

참고 : 때때로 이러한 호출에서 장치가 업데이트되지 않을 수 있으므로 다음과 같이해야합니다.

OrientationController.forceLockOrientation(.portrait)
OrientationController.forceLockOrientation(.landscapeRight)

그게 다야


9

이것은 iOS 6 이상에서 작동하지만 iOS 8에서만 테스트했습니다. 서브 클래스 UINavigationController및 다음 메소드를 재정의하십시오.

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationLandscapeRight;
}

- (BOOL)shouldAutorotate {
    return NO;
}

또는 보이는 뷰 컨트롤러에 문의하십시오

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return self.visibleViewController.preferredInterfaceOrientationForPresentation;
}

- (BOOL)shouldAutorotate {
    return self.visibleViewController.shouldAutorotate;
}

거기에 메소드를 구현하십시오.


iOS 10.0을 실행하는 Xcode 8.2.1의 내 앱에서 이것을 테스트했으며 작동합니다. 내 게임 메뉴는 첫 번째 화면이며 회전하지 않습니다. 다른 모든 뷰는 회전합니다. 완전한! 하나를 줘. Mojo66에서 제공하는 'preferredInterfaceOrientationForPresentation'함수 만 필요했습니다.
Philip Borges

9

다음 을 사용하여 애니메이션을 비활성화하는 방법에 관한 Sid Shah의 답변 에 대한 의견에 대한 피드백입니다 .

[UIView setAnimationsEnabled:enabled];

암호:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:NO];
    [UIView setAnimationsEnabled:NO];

    // Stackoverflow #26357162 to force orientation
    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:NO];
    [UIView setAnimationsEnabled:YES];
}

인물 사진에 어떻게 이것을 사용할 수 있습니까?
Muju

6

navigationViewController를 사용하는 경우이를위한 고유 한 수퍼 클래스를 작성하고 재정의해야합니다.

- (BOOL)shouldAutorotate {
  id currentViewController = self.topViewController;

  if ([currentViewController isKindOfClass:[SecondViewController class]])
    return NO;

  return YES;
}

이에 회전을 비활성화됩니다 SecondViewController 하지만 당신은 당신의 밀어 경우 SecondViewController를 장치가 세로 방향에있을 때 다음 SecondViewController는 세로 모드로 표시됩니다.

스토리 보드를 사용한다고 가정하십시오. 수동 segue ( 방법 ) 를 작성 하고 "onClick"방법으로 작성해야합니다.

- (IBAction)onPlayButtonClicked:(UIBarButtonItem *)sender {
  NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
  [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
  [self performSegueWithIdentifier:@"PushPlayerViewController" sender:self];
}

슈퍼 클래스가 자동 회전 기능을 비활성화하기 전에 가로 방향을 강제합니다.


6

Xcode 8방법이 속성으로 변환, 다음과 같은 작품을 그렇게 Swift:

override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.portrait
}

override public var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return UIInterfaceOrientation.portrait
}

override public var shouldAutorotate: Bool {
    return true
}

방향이 고정됩니까?
bnussey

1
@ bnussey 나는 portraitiPad의 방향에 관계없이 자동 회전을 막고 항상 모드 에 있기를 원 shouldAutorotate했습니다.
Ali Momen Sani

4

나는 많은 솔루션을 시도했지만 효과가 있었던 것은 다음과 같습니다.

info.plistiOS 8 및 9에서 편집 할 필요가 없습니다 .

- (BOOL) shouldAutorotate {
    return NO;
}   

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return (UIInterfaceOrientationPortrait | UIInterfaceOrientationPortraitUpsideDown);
}

Apple 문서에서 가능한 오리엔테이션 :

UIInterfaceOrientationUnknown

장치의 방향을 결정할 수 없습니다.

UIInterfaceOrientationPortrait

기기가 세로 모드이고 기기가 똑바로 세워져 있고 홈 버튼이 아래쪽에 있습니다.

UIInterfaceOrientationPortraitUpsideDown

기기가 세로 모드이지만 거꾸로되어 있으며 기기를 똑바로 세우고 홈 버튼을 맨 위에 놓습니다.

UIInterfaceOrientationLandscapeLeft

기기가 가로 모드이고 기기가 똑바로 세워져 있고 홈 버튼이 왼쪽에 있습니다.

UI 인터페이스 오리엔테이션 풍경 오른쪽

기기가 가로 모드이고 기기가 똑바로 세워져 있고 홈 버튼이 오른쪽에 있습니다.


3

Sids와 Koreys 답변의 조합이 저에게 효과적이었습니다.

네비게이션 컨트롤러 확장 :

extension UINavigationController {
    public override func shouldAutorotate() -> Bool {
        return visibleViewController.shouldAutorotate()
    }
}

그런 다음 단일보기에서 회전 비활성화

class ViewController: UIViewController {
    override func shouldAutorotate() -> Bool {
        return false
    }
}

그리고 segue 전에 적절한 방향으로 회전

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if (segue.identifier == "SomeSegue")
    {
        let value = UIInterfaceOrientation.Portrait.rawValue;
        UIDevice.currentDevice().setValue(value, forKey: "orientation")
    }
}

이것이 표시되는 뷰 컨트롤러가 항상 세로 방향으로 회전하기 전에 가로 방향으로 보이는 경우 내 문제가 도움이 될 수 있는지 알고 있습니까? 질문은 여기에 있습니다 : stackoverflow.com/questions/30693964/…
dwinnbrown

3

위의 최고 솔루션 :

let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")

제시된 뷰 컨트롤러의 viewDidAppear에서 호출했을 때 나를 위해 작동하지 않았습니다. 그러나 프레젠터 뷰 컨트롤러의 preparForSegue에서 호출했을 때 작동했습니다.

(죄송합니다. 해당 솔루션에 대한 평판이 충분하지 않으므로 다음과 같이 추가해야합니다.)


이 작업을 수행했지만 가로보기 컨트롤러에서 세로보기 컨트롤러로 갈 때 세로로 표시되어야하는보기 컨트롤러가 자체적으로 회전하기 전에 가로로 짧게 표시됩니다. 누군가 내 질문을 돕는 방법을 알고 있다면 여기에 있습니다 : stackoverflow.com/questions/30693964/…
dwinnbrown

뷰 컨트롤러의 @dwinnbrown보기 컨트롤러가 이미 표시되어 있습니다. 대신 viewDidLoad에서 시도해보십시오.
Crashalot

@Crashalot 나는 지금 이것을 고쳤다. 내가 정답으로 표시 한 답변을 참조하십시오.
dwinnbrown

@dwinnbrown 귀하의 질문에 대한 링크가 죽었습니다. 최신 정보? 감사!
Crashalot

@Crashalot 커뮤니티가 삭제했지만 삭제를 취소하기로 투표했습니다. 곧 알려 드리겠습니다
dwinnbrown

3

[iOS9 +] 위의 해결책 중 어느 것도 효과가 없었기 때문에 누군가가 여기까지 완전히 드래그 한 경우,보기를 제시하면 segue로 방향을 변경하려는 경우이를 확인하고 싶을 수 있습니다.

segue의 프리젠 테이션 유형을 확인하십시오. 광산은 '현재 상황에'있었습니다. 전체 화면으로 변경하면 효과가있었습니다.

@GabLeRoux 덕분 에이 솔루션을 찾았습니다.

  • 이 변경 사항은 위의 솔루션과 결합 된 경우에만 작동합니다.

2

내 요구 사항은

  1. 세로 모드에서 모든 뷰 잠금
  2. AVPlayerViewController비디오를 재생 하는 데 사용

비디오가 재생 중일 때 화면이 가로이면 가로가 오른쪽으로 회전하고 가로가 왼쪽으로 회전하도록합니다. 세로 인 경우 세로 모드에서만보기를 잠급니다.

먼저, 정의 supportedInterfaceOrientationsForWindowAppDelegate.swift

var portrait = true
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    if portrait {
        return .Portrait
    } else {
        return .Landscape
    }
}

둘째, 메인 뷰 컨트롤러에서 다음 기능을 정의하십시오.

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    print("\(#function)")
    return .Portrait
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    return .Portrait
}

override func shouldAutorotate() -> Bool {
    return false
}

그런 다음 서브 클래스를 만들어야합니다 AVPlayerViewController

class MyPlayerViewController: AVPlayerViewController {

    var size: CGSize?

    var supportedOrientationMask: UIInterfaceOrientationMask?
    var preferredOrientation: UIInterfaceOrientation?

    override func viewDidLoad() {
        super.viewDidLoad()

        if let size = size {
            if size.width > size.height {
                self.supportedOrientationMask =[.LandscapeLeft,.LandscapeRight]
                self.preferredOrientation =.LandscapeRight
            } else {
                self.supportedOrientationMask =.Portrait
                self.preferredOrientation =.Portrait
            }
        }
    }

이 세 가지 기능을 재정의하십시오. MyPlayerViewController.swift

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return self.supportedOrientationMask!
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    return self.preferredOrientation!
}

사용자가 기기의 가로 방향을 왼쪽 또는 오른쪽으로 회전시킬 수 있으므로 자동 회전을 true로 설정해야합니다

override func shouldAutorotate() -> Bool {
    return true
}

마지막으로, MyPlayerViewController뷰 컨트롤러에서 인스턴스를 생성 하고 속성 크기 값을 설정하십시오.

let playerViewController = MyPlayerViewController()

// Get the thumbnail  
let thumbnail = MyAlbumFileManager.sharedManager().getThumbnailFromMyVideoMedia(......)

let size = thumbnail?.size
playerViewController.size = size

적절한로 플레이어를 시작한 다음에 플레이어 videoUrl를 할당하십시오 playerViewController. 행복한 코딩!



1

이 작업을 수행하는 최선의 방법에 대한 논쟁이 여전히 남아있는 것 같습니다. UIViewController구현에 다음 코드를 추가하십시오 .

- (void) viewWillAppear:(BOOL)animated
{
    [UIViewController attemptRotationToDeviceOrientation];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

-(BOOL)shouldAutorotate
{
    return NO;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscapeLeft;
}

이 예의 경우 프로젝트 설정에서 (또는 직접 info.plist) 허용 된 장치 방향을 '가로 왼쪽'으로 설정해야합니다 . 이외의 다른 것을 원하면 강제로 특정 방향을 변경하십시오.LandscapeLeft.

나를위한 열쇠는 attemptRotationToDeviceOrientation전화 였다viewWillAppear . 뷰가 실제로 장치를 회전시키지 않으면 제대로 회전하지 않습니다.


더 이상 사용되지 않는 방법.
Saqib Omer

1

코리 힌튼의 답변 에 따르면

스위프트 2.2 :

extension UINavigationController {
    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return visibleViewController!.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        return visibleViewController!.shouldAutorotate()
    }
}


extension UITabBarController {
    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations()
        }
        return super.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate()
        }
        return super.shouldAutorotate()
    }
}

회전 비활성화

override func shouldAutorotate() -> Bool {
    return false
}

특정 방향으로 고정

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.Portrait
}

1

나는 여기에 몇 가지 해결책을 시도했으며 이해해야 할 중요한 것은 그것이 회전하는지 아닌지를 결정하는 루트보기 컨트롤러라는 것입니다.

하나의 자식보기가 회전 할 수 있고 다른 자식보기가 세로로 잠겨 있는 작업 예제를 사용 하여 다음 objective-c 프로젝트 github.com/GabLeRoux/RotationLockInTabbedViewChild 를 만들었습니다 TabbedViewController.

완벽하지는 않지만 작동하며 같은 아이디어가와 같은 다른 종류의 루트보기에 작동해야합니다 NavigationViewController. :)

자식 뷰는 부모 방향을 잠급니다


0

@ sid-sha가 보여준 해결책에 따르면 viewDidAppear:메소드 에 모든 것을 넣어야합니다 . 그렇지 않으면 didRotateFromInterfaceOrientation:해고 되지 않을 것입니다.

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
    if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
        interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
        NSNumber *value = [NSNumber numberWithInt:interfaceOrientation];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    }
}

0

내 솔루션

에서 AppDelegate:

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    if let topController = UIViewController.topMostViewController() {
        if topController is XXViewController {
            return [.Portrait, .LandscapeLeft]
        }
    }
    return [.Portrait]
}

XXViewController 가로 모드를 지원하려는 ViewController입니다.

그런 다음 Sunny Shah의 솔루션XXViewController모든 iOS 버전 에서 작동합니다 .

let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")

이것은 최상위 ViewController를 찾는 유틸리티 함수입니다.

extension UIViewController {

    /// Returns the current application's top most view controller.
    public class func topMostViewController() -> UIViewController? {
        let rootViewController = UIApplication.sharedApplication().windows.first?.rootViewController
        return self.topMostViewControllerOfViewController(rootViewController)
    }



    /// Returns the top most view controller from given view controller's stack.
    class func topMostViewControllerOfViewController(viewController: UIViewController?) -> UIViewController? {
        // UITabBarController
        if let tabBarController = viewController as? UITabBarController,
           let selectedViewController = tabBarController.selectedViewController {
            return self.topMostViewControllerOfViewController(selectedViewController)
        }

        // UINavigationController
        if let navigationController = viewController as? UINavigationController,
           let visibleViewController = navigationController.visibleViewController {
            return self.topMostViewControllerOfViewController(visibleViewController)
        }

        // presented view controller
        if let presentedViewController = viewController?.presentedViewController {
            return self.topMostViewControllerOfViewController(presentedViewController)
        }

        // child view controller
        for subview in viewController?.view?.subviews ?? [] {
            if let childViewController = subview.nextResponder() as? UIViewController {
                return self.topMostViewControllerOfViewController(childViewController)
            }
        }

        return viewController
    }

}

0

이것을 사용하여 IOS 9에서 테스트 된 뷰 컨트롤러 방향을 잠급니다.

// 가로 방향으로 잠금

-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscapeRight;
}

-(NSUInteger)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController {
    return UIInterfaceOrientationMaskLandscapeRight;
}

0

나는 같은 문제가 있고 많은 시간을 낭비합니다. 이제 솔루션이 있습니다. 내 응용 프로그램 설정이 단지 지원 초상화 only.However, 내 응용 프로그램에 일부 화면은 문제를 해결하여 변수가 only.I 풍경이 필요 isShouldRotate을 에서 AppDelegate에를 . 그리고 AppDelegate 의 기능 :

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
    if isShouldRotate == true {
        return Int(UIInterfaceOrientationMask.Landscape.rawValue)
    }
    return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}

그리고 마지막으로 ViewControllerA에 가로 상태가 필요할 때 . 그냥 그렇게 : 푸시 / 현재 이전ViewControllerA에 할당 isShouldRotate사실 . viewWillDisappear 에서 컨트롤러가 isShouldRotatefalse 로 지정하는 팝업 / 해제 시점을 잊지 마십시오 .


0

나를 위해 최상위 VC는 방향 재정의를 구현해야했습니다. VC 다운을 사용하면 최상위 VC가 구현되지 않은 경우 스택이 영향을 미치지 않습니다.

VC-main
    |
    -> VC 2
        |
        -> VC 3

본질적으로 내 테스트에서 VC-Main 만 들었습니다.


0

여기조차도 아무도 나를 위해 충분하지 않은 답변이 너무 많은 것 같습니다. 방향을 강요하고 다시 장치 방향으로 돌아가고 싶었지만[UIViewController attemptRotationToDeviceOrientation]; 작동 않았습니다. 또한 복잡한 전체 작업은 일부 답변을 기반으로 shouldAutorotate를 false로 추가했으며 모든 시나리오에서 올바르게 되돌릴 수있는 원하는 효과를 얻을 수 없다는 것입니다.

이것이 내가 한 일입니다.

초기화 생성자에서 호출중인 컨트롤러를 푸시하기 전에 다음을 수행하십시오.

_userOrientation = UIDevice.currentDevice.orientation;
[UIDevice.currentDevice setValue:@(UIInterfaceOrientationPortrait) forKey:@"orientation"];
[self addNotificationCenterObserver:@selector(rotated:)
                               name:UIDeviceOrientationDidChangeNotification];

그래서 마지막 장치 방향을 저장하고 방향 변경 이벤트에 등록합니다. 오리엔테이션 변경 이벤트는 간단합니다 :

- (void)rotated:(NSNotification*)notification {
    _userOrientation = UIDevice.currentDevice.orientation;
}

그리고보기가 잘못되면, 나는 userOreintation으로 가지고있는 방향으로 되돌립니다.

- (void)onViewDismissing {
    super.onViewDismissing;
    [UIDevice.currentDevice setValue:@(_userOrientation) forKey:@"orientation"];
    [UIViewController attemptRotationToDeviceOrientation];
}

그리고 이것도 있어야합니다.

- (BOOL)shouldAutorotate {
    return true;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

또한 탐색 컨트롤러는 shouldAutorotate 및 supportedInterfaceOrientations에 위임해야하지만 대부분의 사람들은 이미 믿습니다.

추신 : 일부 확장 프로그램과 기본 클래스를 사용하여 죄송하지만 이름은 매우 의미가 있으므로 개념을 이해할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.