source

Swift를 사용하여 하나의 View 컨트롤러에 가로 모드 적용

nicesource 2023. 9. 1. 21:07
반응형

Swift를 사용하여 하나의 View 컨트롤러에 가로 모드 적용

응용 프로그램에서 가로 모드로 하나의 보기만 강제로 설정하려고 합니다. 호출합니다.

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

override func supportedInterfaceOrientations() -> Int {
    print("supportedInterfaceOrientations")
    return Int(UIInterfaceOrientationMask.LandscapeLeft.rawValue)
}

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

보기가 세로 모드로 시작되고 장치 방향을 변경하면 계속 회전합니다.shouldAutorotate()메서드가 호출되지 않습니다.

어떤 도움이라도 주시면 감사하겠습니다.

다른 사용자에게 유용할 수 있습니다. 보기를 가로 모드로 강제 실행하는 방법을 찾았습니다.

DidLoad() 보기에 저장합니다.

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

그리고.

override var shouldAutorotate: Bool {
    return true
}

스위프트 4

override func viewDidLoad() {
    super.viewDidLoad()
    let value = UIInterfaceOrientation.landscapeLeft.rawValue
    UIDevice.current.setValue(value, forKey: "orientation")
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .landscapeLeft
}

override var shouldAutorotate: Bool {
    return true
}

보기가 탐색 컨트롤러에 내장된 경우 위의 항목만 사용할 수 없습니다.클래스 정의 후 다음 확장자까지 단계적으로 진행해야 합니다.

extension UINavigationController {

override open var shouldAutorotate: Bool {
    get {
        if let visibleVC = visibleViewController {
            return visibleVC.shouldAutorotate
        }
        return super.shouldAutorotate
    }
}

override open var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation{
    get {
        if let visibleVC = visibleViewController {
            return visibleVC.preferredInterfaceOrientationForPresentation
        }
        return super.preferredInterfaceOrientationForPresentation
    }
}

override open var supportedInterfaceOrientations: UIInterfaceOrientationMask{
    get {
        if let visibleVC = visibleViewController {
            return visibleVC.supportedInterfaceOrientations
        }
        return super.supportedInterfaceOrientations
    }
}}


스위프트 3

override func viewDidLoad() {
    super.viewDidLoad()
    let value = UIInterfaceOrientation.landscapeLeft.rawValue
    UIDevice.current.setValue(value, forKey: "orientation")
}

private func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.landscapeLeft
}

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

Swift 4, iOS 11에서 테스트 완료

projectTarget -> General -> DeploymentInfo (Device Orientation) -> Portrait (가로좌측 및 가로우측은 선택사항)에서 방향을 지정할 수 있습니다.

앱 대표자

    var myOrientation: UIInterfaceOrientationMask = .portrait
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return myOrientation
    }

LandScpae 뷰 컨트롤러

override func viewDidLoad() {
        super.viewDidLoad()
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.myOrientation = .landscape
}

온 디스미스버튼탭

let appDelegate = UIApplication.shared.delegate as! AppDelegate
 appDelegate.myOrientation = .portrait

바로 그거야.:)

Swift 2.2 사용

시도:

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

다음 사용자:

UIViewController.attemptRotationToDeviceOrientation()

Apple의 UIView 컨트롤러 클래스 참조:

일부 뷰 컨트롤러는 앱별 조건을 사용하여 지원되는 인터페이스 방향을 결정할 수 있습니다.보기 컨트롤러에서 이 작업을 수행하는 경우 이러한 조건이 변경되면 앱에서 이 클래스 메소드를 호출해야 합니다.시스템이 즉시 새 방향으로 회전을 시도합니다.

그런 다음 다른 사용자가 제안한 대로 다음 방법을 적절히 재정의합니다.

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

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

시그니처 뷰와 비슷한 문제를 겪고 있었는데 이것으로 해결되었습니다.

AppDelegate에서 다음을 추가합니다.

//Orientation Variables
var myOrientation: UIInterfaceOrientationMask = .portrait

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

방향을 변경하려는 viewController에 다음을 추가합니다.

override func viewDidLoad() {
        super.viewDidLoad()
        self.rotateToLandsScapeDevice()
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.rotateToPotraitScapeDevice()
    }

    func rotateToLandsScapeDevice(){
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.myOrientation = .landscapeLeft
        UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")
        UIView.setAnimationsEnabled(true)
    }

    func rotateToPotraitScapeDevice(){
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.myOrientation = .portrait
        UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
        UIView.setAnimationsEnabled(true)
    }

저는 Zeesha의 답변과 Sazz의 답변을 종합한 결과가 가장 좋았습니다.

AppDelegate.swift에 다음 행을 추가합니다.

var orientationLock = UIInterfaceOrientationMask.portrait
var myOrientation: UIInterfaceOrientationMask = .portrait
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return myOrientation
}  

다음 행을 뷰 컨트롤러 클래스에 추가합니다.

let appDel = UIApplication.shared.delegate as! AppDelegate

행을 뷰 의 보다행컨에추에 합니다.viewDidLoad():

appDel.myOrientation = .landscape
UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")

(선택사항) 해제 기능에 다음 행을 추가합니다.

appDel.myOrientation = .portrait
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")

이러한 코드 라인이 수행하는 작업은 기본 방향을 세로로 설정하고 뷰 컨트롤러가 로드될 때 가로로 회전한 다음 뷰 컨트롤러가 닫히면 세로로 다시 재설정하는 것입니다.

덮어쓰기(ViewController에서):

override public var shouldAutorotate: Bool {
    return false
} 

override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .landscapeRight
}

override public var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return .landscapeRight
}

IOS 13에 대한 힌트.13 는 IOS 13과 다른 VC를 가지고 .modalPresentationStyle~하듯이.automatic및 장치는 전체 화면 VC 대신 모달 뷰를 제공합니다.이 문제를 해결하려면 설정해야 합니다.modalPresentationStyle.fullScreen예:

let viewController = YourViewController()
viewController.modalPresentationStyle = .fullScreen

컨트롤러 하나를 세로 방향으로 강제 배치해야 했습니다.이것을 추가하는 것은 저에게 효과가 있었습니다.

iOS 11을 사용하는 swift 4

override var   supportedInterfaceOrientations : UIInterfaceOrientationMask{

    return  .portrait

}

저는 제 프로젝트에서 비슷한 문제에 직면했습니다.초상화만 지원됩니다.ViewController 구조는 Navigation에 컨트롤러(A라고 함)와 긴 ScrollView가 포함되어 있다는 것입니다.저는 B(가로 오른쪽)에게 A(세로 오른쪽)를 선물해야 합니다.

처음에는 아래의 방법을 시도해 보았는데 효과가 있는 것 같았지만 결국 버그를 발견했습니다.

스위프트 5 & iOS12

// In B controller just override three properties

override var shouldAutorotate: Bool {
    return false
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.landscapeRight
}

override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return .landscapeRight
}

그리고는 뭔가 이상해집니다.컨트롤러 B가 컨트롤러 A로 해제될 때.컨트롤러 A의 ScrollView가 슬라이드되었습니다.

그래서 저는 다른 방법을 사용해서 화면을 돌립니다.viewWillAppear당신은 아래의 코드를 볼 수 있습니다.

// In controller B
// not need override shouldAutorotate , supportedInterfaceOrientations , preferredInterfaceOrientationForPresentation

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    let appDel = UIApplication.shared.delegate as! AppDelegate
    appDel.currentOrientation = .landscapeRight
    UIDevice.current.setValue( UIInterfaceOrientation.landscapeRight.rawValue, forKey: "orientation")
    UIViewController.attemptRotationToDeviceOrientation()
}

//in viewWillDisappear rotate to portrait can not fix the bug


override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
    let appDel = UIApplication.shared.delegate as! AppDelegate
    appDel.currentOrientation = .portrait
    UIDevice.current.setValue( UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
    UIViewController.attemptRotationToDeviceOrientation() //must call 
    super.dismiss(animated: true, completion: nil)
}
// in AppDelegate
// the info plist is only supported portrait also, No need to change it

var currentOrientation : UIInterfaceOrientationMask = .portrait


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

Swift 2.2에서 작동

 func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    if self.window?.rootViewController?.presentedViewController is SignatureViewController {

        let secondController = self.window!.rootViewController!.presentedViewController as! SignatureViewController

        if secondController.isPresented {

            return UIInterfaceOrientationMask.LandscapeLeft;

        } else {

            return UIInterfaceOrientationMask.Portrait;
        }

    } else {

        return UIInterfaceOrientationMask.Portrait;
    }
}

스위프트 3.이렇게 하면 사용자가 앱을 다시 열 때마다 방향이 잠깁니다.

class MyViewController: UIViewController {
    ...
    override func viewDidLoad() {
        super.viewDidLoad()

        // Receive notification when app is brought to foreground
        NotificationCenter.default.addObserver(self, selector: #selector(self.onDidBecomeActive), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)
    }

    // Handle notification
    func onDidBecomeActive() {
        setOrientationLandscape()
    }

    // Change orientation to landscape
    private func setOrientationLandscape() {
        if !UIDevice.current.orientation.isLandscape {
            let value = UIInterfaceOrientation.landscapeLeft.rawValue
            UIDevice.current.setValue(value, forKey:"orientation")
            UIViewController.attemptRotationToDeviceOrientation()
        }
    }

    // Only allow landscape left
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.landscapeLeft
    }

    /*
    // Allow rotation - this seems unnecessary
    private func shouldAutoRotate() -> Bool {
        return true
    }
    */
    ...
}

스위프트 4

오리엔테이션을 유지하려고 노력하는 것 외에는 아무 것도 효과가 없었습니다.

...        
override func viewDidLoad() {
       super.viewDidLoad()
       forcelandscapeRight()
       let notificationCenter = NotificationCenter.default
       notificationCenter.addObserver(self, selector: #selector(forcelandscapeRight), name: Notification.Name.UIDeviceOrientationDidChange, object: nil)
    }

    @objc func forcelandscapeRight() {
        let value = UIInterfaceOrientation.landscapeRight.rawValue
        UIDevice.current.setValue(value, forKey: "orientation")
    }
....

ViewController의 ViewDidLoad 메서드에서 아래 함수를 호출합니다.

func rotateDevice(){
    UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")
    UIView.setAnimationsEnabled(true) // while rotating device it will perform the rotation animation
}`

앱 위임 파일 아래에 함수 및 변수 추가

//Orientation Variables
var orientationLock = UIInterfaceOrientationMask.portrait
var myOrientation: UIInterfaceOrientationMask = .portrait

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

지원되는 문서에 따라인터페이스 방향shouldAutorotate는 메드가반야합니다어되를 .true또는YES에서 목-C서, 그가 되도록 .supportedInterfaceOrientations고려됩니다.

iOS 16+:requestGeometryUpdate(_:errorHandler:)API

트위터에서 @simonbs가 언급한 바와 같이, iOS 16은 현재 인터페이스 방향을 업데이트하기 위한 새로운 API도입합니다.대부분의 경우에는 다른 기존 방법이 작업을 수행하지만, 일부 에지의 경우에는 작동하지 않습니다( 답변에서 제안한 대로 개인 API를 사용하도록 강제함).여기서 새로운 공개 API가 도움이 됩니다.

API는 다음과 같이 작동합니다.

windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait))

오류를 처리하기 위해 선택적으로 폐쇄를 통과할 수도 있습니다(오류가 발생할 수 있는 상황에 대한 경험은 없지만).

windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait)) { error in
   // Handle error...
}

나의 해결책은

방금 AppDelegate에서 아래 코드를 추가했습니다.

enum PossibleOrientations {
  case portrait
    case landscape

    func o() -> UIInterfaceOrientationMask {
      switch self {
      case .portrait:
        return .portrait
      case .landscape:
        return .landscapeRight
      }
    }
}
var orientation: UIInterfaceOrientationMask = .portrait

func switchOrientation(to: PossibleOrientations) {
    let keyOrientation = "orientation"

    if to == .portrait && UIDevice.current.orientation.isPortrait {
        return
    } else if to == .landscape && UIDevice.current.orientation.isLandscape {
        return
    }

    switch to {
    case .portrait:
        orientation = .portrait
        UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: keyOrientation)
    case .landscape:
        orientation = .landscapeRight
        UIDevice.current.setValue(UIInterfaceOrientation.landscapeRight.rawValue, forKey: keyOrientation)
    }
}

변경하려면 아래 코드로 전화하십시오.

override func viewDidLoad() {
    super.viewDidLoad()

    if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
        appDelegate.switchOrientation(to: .landscape)
    }
}

또는 아래와 같이

@IBAction func actBack() {
    if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
        appDelegate.switchOrientation(to: .portrait)
    }
    self.navigationController?.popViewController(animated: true)
}
// below code put in view controller
// you can change landscapeLeft or portrait

override func viewWillAppear(_ animated: Bool) {
        UIDevice.current.setValue(UIInterfaceOrientation.landscapeRight.rawValue, forKey: "orientation")
    }

override var shouldAutorotate: Bool {
        return true
    }
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .landscapeRight
    }
    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
        return .landscapeRight
    }

아래의 많은 답변을 시도해 보았지만 효과가 없었습니다.특히 앱에서 네비게이션 바와 탭 바도 구현되는 경우에는 더욱 그렇습니다.저에게 효과가 있었던 해결책은 Sunny Lee가 여기 게시물에 제공했습니다: Sunny Lee, 중간 게시물

다음은 이 게시물의 업데이트입니다.원해

게시물의 솔루션을 구현할 때 변경한 것은 .But UpsideDown을 제외한 나머지 부분을 .landscape left로 변경한 것뿐입니다.

스위프트 5가 탑재된 Xcode 11에서 나는 다음을 구현했습니다.그러나 프로젝트 대상에 대한 장치 방향이 모든 방향을 포함하지 않는 경우에만 작동합니다.Upside Down 확인을 비활성화했습니다.이 이후에는 다음 코드가 작동합니다.모든 확인란이 활성화된 경우 코드가 호출되지 않습니다.

class MyController : UINavigationController {

    override var shouldAutorotate: Bool {
        return true
    }

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .landscape
    }


}

IOS 13 ~ 16.4에서 테스트됨

먼저 회전식 보기 컨트롤러에 대한 프로토콜을 만듭니다.

protocol Rotatable:UIViewController{}

그 다음 아래 코드를 추가합니다.AppDelegate:

 func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    guard let topVC = UIApplication.getTopViewController(base: window?.rootViewController) as? Rotatable else {
        return .portrait
    }
    guard !topVC.isModal else {
        //Use isBeingDismissed to prevent rotation glitches when changing the top view controller.
        return topVC.isBeingDismissed ? .portrait : topVC.supportedInterfaceOrientations
    }

    return topVC.supportedInterfaceOrientations
}

다음 확장자도 필요합니다.

extension UIApplication {

    static func getTopViewController(base: UIViewController? = rootViewController) -> UIViewController? {
        
        if let nav = base as? UINavigationController {
            return getTopViewController(base: nav.visibleViewController)
        }

        if let tab = base as? UITabBarController {
            if let selected = tab.selectedViewController {
                return getTopViewController(base: selected)
            }
        }

        if let presented = base?.presentedViewController {
            return getTopViewController(base: presented)
        }

        return base
    }
    
    static var rootViewController:UIViewController?{
      return UIApplication
            .shared
            .connectedScenes
            .flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
            .last { $0.isKeyWindow }?.rootViewController
    }

}


extension UIViewController{
    
    var isModal: Bool {

        let presentingIsModal = presentingViewController != nil
        let presentingIsNavigation = navigationController?.presentingViewController?.presentedViewController == navigationController
        let presentingIsTabBar = tabBarController?.presentingViewController is UITabBarController

        return presentingIsModal || presentingIsNavigation || presentingIsTabBar
    }
    
}

그런 다음 뷰 컨트롤러에서 다음 변수를 재정의하면 됩니다.

class MyViewController: UIViewController,Rotatable {

     override var shouldAutorotate: Bool {
            return true
        }
        
     override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
            return .landscape
        }

}
class CustomUIViewController : UIViewController{

    override var   supportedInterfaceOrientations : UIInterfaceOrientationMask{

        return  .landscapeLeft

    }

}


class ViewController: CustomUIViewController {
.
.
.
}

언급URL : https://stackoverflow.com/questions/27037839/force-landscape-mode-in-one-viewcontroller-using-swift

반응형