[ios] Swift-방향 변경 감지 방법

단일 이미지보기 (예 : 가로 이미지 및 세로 이미지)에 두 개의 이미지를 추가하고 싶지만 빠른 언어를 사용하여 방향 변경을 감지하는 방법을 모르겠습니다.

이 대답을 시도했지만 하나의 이미지 만 걸립니다.

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.currentDevice().orientation.isLandscape.boolValue {
        print("Landscape")
    } else {
        print("Portrait")
    }
}

나는 iOS 개발에 익숙하지 않습니다. 어떤 조언이라도 대단히 감사하겠습니다!



답변

let const = "Background" //image name
let const2 = "GreyBackground" // image name
    @IBOutlet weak var imageView: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.image = UIImage(named: const)
        // Do any additional setup after loading the view.
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        if UIDevice.current.orientation.isLandscape {
            print("Landscape")
            imageView.image = UIImage(named: const2)
        } else {
            print("Portrait")
            imageView.image = UIImage(named: const)
        }
    }


답변

사용 NotificationCenterUIDevice 의를beginGeneratingDeviceOrientationNotifications

Swift 4.2 이상

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
}

deinit {
   NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
}

func rotated() {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
    } else {
        print("Portrait")
    }
}

스위프트 3

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}

deinit {
     NotificationCenter.default.removeObserver(self)
}

func rotated() {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
    } else {
        print("Portrait")
    }
}


답변

Swift 3
위 코드 업데이트 :

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
    } else {
        print("Portrait")
    }
}


답변

⚠️ 장치 방향! = 인터페이스 방향 ⚠️

Swift 5. * iOS14 이하

정말 다음과 같은 차이를 만들어야합니다.

  • 장치 방향 => 물리적 장치의 방향을 나타냅니다.
  • 인터페이스 방향 => 화면에 표시된 인터페이스의 방향을 나타냅니다.

다음과 같이 두 값이 일치하지 않는 많은 시나리오가 있습니다.

  • 화면 방향을 잠글 때
  • 장치가 평평 할 때

대부분의 경우 인터페이스 방향을 사용하고 싶고 창을 통해 가져올 수 있습니다.

private var windowInterfaceOrientation: UIInterfaceOrientation? {
    return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
}

<iOS 13 (예 : iOS 12)도 지원하려면 다음을 수행합니다.

private var windowInterfaceOrientation: UIInterfaceOrientation? {
    if #available(iOS 13.0, *) {
        return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
    } else {
        return UIApplication.shared.statusBarOrientation
    }
}

이제 창 인터페이스 방향 변경에 반응 할 위치를 정의해야합니다. 이를 수행하는 방법에는 여러 가지가 있지만 최적의 솔루션은 내에서 수행하는 것입니다
willTransition(to newCollection: UITraitCollection.

재정의 될 수있는이 상속 된 UIViewController 메서드는 인터페이스 방향이 변경 될 때마다 트리거됩니다. 결과적으로 후자에서 모든 수정을 수행 할 수 있습니다.

다음은 솔루션 예입니다.

class ViewController: UIViewController {
    override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
        super.willTransition(to: newCollection, with: coordinator)

        coordinator.animate(alongsideTransition: { (context) in
            guard let windowInterfaceOrientation = self.windowInterfaceOrientation else { return }

            if windowInterfaceOrientation.isLandscape {
                // activate landscape changes
            } else {
                // activate portrait changes
            }
        })
    }

    private var windowInterfaceOrientation: UIInterfaceOrientation? {
        return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
    }
}

이 메서드를 구현하면 인터페이스 방향 변경에 반응 할 수 있습니다. 그러나 앱을 열 때 트리거되지 않으므로에서 인터페이스를 수동으로 업데이트해야합니다 viewWillAppear().

장치 방향과 인터페이스 방향의 차이를 강조하는 샘플 프로젝트를 만들었습니다. 또한 UI를 업데이트하기로 결정한 수명주기 단계에 따라 다른 동작을 이해하는 데 도움이됩니다.

다음 저장소를 자유롭게 복제하고 실행하십시오 :
https://github.com/wjosset/ReactToOrientation


답변

Swift 4+ :
소프트 키보드 디자인을 위해 이것을 사용 UIDevice.current.orientation.isLandscape하고 있었는데 Portrait, 어떤 이유로 든 방법이 계속라고 말 했으니, 대신에 제가 사용한 것은 다음과 같습니다.

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    if(size.width > self.view.frame.size.width){
        //Landscape
    }
    else{
        //Portrait
    }
}


답변

Swift 4.2, RxSwift

collectionView를 다시로드해야하는 경우.

NotificationCenter.default.rx.notification(UIDevice.orientationDidChangeNotification)
    .observeOn(MainScheduler.instance)
    .map { _ in }
    .bind(to: collectionView.rx.reloadData)
    .disposed(by: bag)

스위프트 4, RxSwift

collectionView를 다시로드해야하는 경우.

NotificationCenter.default.rx.notification(NSNotification.Name.UIDeviceOrientationDidChange)
    .observeOn(MainScheduler.instance)
    .map { _ in }
    .bind(to: collectionView.rx.reloadData)
    .disposed(by: bag)


답변

: 나는 정답 실제로이 둘의 조합이 접근 생각 viewWIllTransition(toSize:)하고 NotificationCenterUIDeviceOrientationDidChange.

viewWillTransition(toSize:)전환 전에 알려줍니다 .

NotificationCenter UIDeviceOrientationDidChange후에 알려줍니다 .

매우 조심해야합니다. 예를 들어, UISplitViewController장치가 특정 방향으로 회전하면 의 배열에서 DetailViewController튀어 나와 마스터의 . 회전이 완료되기 전에 디테일 뷰 컨트롤러를 검색하면 존재하지 않고 충돌 할 수 있습니다.UISplitViewControllerviewcontrollersUINavigationController