Programing

Swift-방향 변경 감지 방법

lottogame 2020. 11. 3. 07:36
반응형

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)
        }
    }

Swift 3 위 코드 업데이트 :

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
    } else {
        print("Portrait")
    }
}

NotificationCenter를 사용하는 Swift 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 4+ : 저는 소프트 키보드 디자인에 이것을 사용 UIDevice.current.orientation.isLandscape하고 있었는데 Portrait, 어떤 이유에서인지 방법이 계속라고 말 했으니, 대신 제가 사용한 것은 다음과 같습니다.

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    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)

Swift 버전> = 3.0을 사용하는 경우 다른 사람들이 이미 말한대로 적용해야하는 일부 코드 업데이트가 있습니다. super에 전화하는 것을 잊지 마세요.

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

   super.viewWillTransition(to: size, with: coordinator)

   // YOUR CODE OR FUNCTIONS CALL HERE

}

이미지에 StackView를 사용하려는 경우 다음과 같은 작업을 수행 할 수 있습니다.

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

   super.viewWillTransition(to: size, with: coordinator)

   if UIDevice.current.orientation.isLandscape {

      stackView.axis = .horizontal

   } else {

      stackView.axis = .vertical

   } // else

}

Interface Builder를 사용하는 경우 오른쪽 패널의 Identity Inspector 섹션에서이 UIStackView 객체에 대한 사용자 정의 클래스를 선택하는 것을 잊지 마십시오. 그런 다음 (Interface Builder를 통해) 사용자 정의 UIStackView 인스턴스에 대한 IBOutlet 참조를 만듭니다.

@IBOutlet weak var stackView: MyStackView!

아이디어를 취하고 필요에 맞게 조정하십시오. 이것이 당신을 도울 수 있기를 바랍니다!


스위프트 4

를 사용하여 ViewControllers 뷰를 업데이트 할 때 UIDevice.current.orientation하위 뷰의 회전 또는 애니메이션 중 테이블 뷰 셀의 제약 조건을 업데이트하는 것과 같은 몇 가지 사소한 문제가있었습니다 .

Instead of the above methods I am currently comparing the transition size to the view controllers view size. This seems like the proper way to go since one has access to both at this point in code:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    print("Will Transition to size \(size) from super view size \(self.view.frame.size)")

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

    if (size.width != self.view.frame.size.width) {
        // Reload TableView to update cell's constraints.
    // Ensuring no dequeued cells have old constraints.
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    }


}

Output on a iPhone 6:

Will Transition to size (667.0, 375.0) from super view size (375.0, 667.0) 
Will Transition to size (375.0, 667.0) from super view size (667.0, 375.0)

I believe the correct answer is actually a combination of both approaches: viewWIllTransition(toSize:) and NotificationCenter's UIDeviceOrientationDidChange.

viewWillTransition(toSize:) notifies you before the transition.

NotificationCenter UIDeviceOrientationDidChange notifies you after.

You have to be very careful. For example, in UISplitViewController when the device rotates into certain orientations, the DetailViewController gets popped off the UISplitViewController's viewcontrollers array, and pushed onto the master's UINavigationController. If you go searching for the detail view controller before the rotation has finished, it may not exist and crash.


All previous contributes are fine, but a little note:

a) if orientation is set in plist, only portrait or example, You will be not notified via viewWillTransition

b) if we anyway need to know if user has rotated device, (for example a game or similar..) we can only use:

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

tested on Xcode8, iOS11


To get the correct orientation on app start you have to check it in viewDidLayoutSubviews(). Other methods described here won't work.

Here's an example how to do it:

var mFirstStart = true

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    if (mFirstStart) {
        mFirstStart = false
        detectOrientation()
    }
}

func detectOrientation() {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
        // do your stuff here for landscape
    } else {
        print("Portrait")
        // do your stuff here for portrait
    }
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    detectOrientation()
}

This will work always, on app first start, and if rotating while the app is running.

참고URL : https://stackoverflow.com/questions/38894031/swift-how-to-detect-orientation-changes

반응형