Swift - 방향 변화를 감지하는 방법
단일 이미지 뷰에 2개의 이미지를 추가하고 싶은데(한 이미지는 가로로, 다른 이미지는 세로로) 빠른 언어를 사용하여 방향 변화를 감지하는 방법을 알 수 없습니다.
나는 이 대답을 시도해 보았지만, 그것은 하나의 이미지만을 가지고 있다.
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)
}
}
Notification Center 및 UIDevice 사용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 5.* iOS16 이하
다음과 같은 차이를 두어야 합니다.
- 디바이스 방향 => 물리 디바이스의 방향을 나타냅니다.
- Interface Orientation(인터페이스 방향) => 화면에 표시되는 인터페이스의 방향을 나타냅니다.
이들 2개의 값이 일치하지 않는 시나리오는 다음과 같습니다.
- 화면 방향을 잠글 때
- 단말기가 플랫인 경우
대부분의 경우 인터페이스 방향을 사용하고 싶기 때문에 창을 통해 얻을 수 있습니다.
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 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 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 버전 > = 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!
아이디어를 받아들여 니즈에 맞게 조정하십시오.도움이 되길 바랍니다!
Swift 4.2, RxSwift
collectionView를 새로고침해야 하는 경우.
NotificationCenter.default.rx.notification(UIDevice.orientationDidChangeNotification)
.observeOn(MainScheduler.instance)
.map { _ in }
.bind(to: collectionView.rx.reloadData)
.disposed(by: bag)
Swift 4, RxSwift
collectionView를 새로고침해야 하는 경우.
NotificationCenter.default.rx.notification(NSNotification.Name.UIDeviceOrientationDidChange)
.observeOn(MainScheduler.instance)
.map { _ in }
.bind(to: collectionView.rx.reloadData)
.disposed(by: bag)
다음은 최신 Combine 솔루션입니다.
import UIKit
import Combine
class MyClass: UIViewController {
private var subscriptions = Set<AnyCancellable>()
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter
.default
.publisher(for: UIDevice.orientationDidChangeNotification)
.sink { [weak self] _ in
let orientation = UIDevice.current.orientation
print("Landscape: \(orientation.isLandscape)")
}
.store(in: &subscriptions)
}
}
두합니다.viewWIllTransition(toSize:) ★★★★★★★★★★★★★★★★★」NotificationCenter의 »UIDeviceOrientationDidChange.
viewWillTransition(toSize:)는 이행 전에 통지합니다.
NotificationCenter UIDeviceOrientationDidChange가 다음에 통지합니다.
아주 조심해야 합니다.를 들어, 「 」에서는,UISplitViewController가 특정때, 「동작」은, 「동작」으로 회전합니다.DetailViewController the the the the 에서 떨어지다UISplitViewController의 »viewcontrollers어레인지로 .UINavigationController로테이션이 종료되기 전에 상세 뷰 컨트롤러를 검색하면 컨트롤러가 존재하지 않고 크래쉬 할 수 있습니다.
스위프트 4
를 사용하여 할 때 약간의 UIDevice.current.orientation예를 들어, 회전 중 또는 서브뷰 애니메이션 중에 테이블뷰 셀의 구속조건을 갱신하는 등입니다.
현재 위의 방법 대신 전환 크기를 뷰 컨트롤러 뷰 크기와 비교하고 있습니다.코드의 이 시점에서 양쪽 모두에 액세스 할 수 있기 때문에, 이것은 적절한 방법이라고 생각됩니다.
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()
}
}
}
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)
하시면 됩니다.viewWillTransition(to:with:)에 접속합니다.animate(alongsideTransition:completion:)전환 완료 후 인터페이스 방향을 얻습니다.이벤트를 이용하려면 이와 유사한 프로토콜을 정의하고 구현해야 합니다.이 코드는 SpriteKit 게임에 사용되었으며 구현 방식이 다를 수 있습니다.
protocol CanReceiveTransitionEvents {
func viewWillTransition(to size: CGSize)
func interfaceOrientationChanged(to orientation: UIInterfaceOrientation)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
guard
let skView = self.view as? SKView,
let canReceiveRotationEvents = skView.scene as? CanReceiveTransitionEvents else { return }
coordinator.animate(alongsideTransition: nil) { _ in
if let interfaceOrientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation {
canReceiveRotationEvents.interfaceOrientationChanged(to: interfaceOrientation)
}
}
canReceiveRotationEvents.viewWillTransition(to: size)
}
이러한 함수에 중단점을 설정하고 다음을 관찰할 수 있습니다.interfaceOrientationChanged(to orientation: UIInterfaceOrientation) ', 하다'의 이름을 부르죠.viewWillTransition(to size: CGSize)신신오최
이전 기고문은 모두 문제 없습니다만, 조금 주의해 주세요.
a) plist, 세로 또는 예시로 방향이 설정되어 있는 경우 view Transition을 통해 알리지 않습니다.
b) 사용자가 기기를 회전했는지 여부를 알 필요가 있는지 여부(예를 들어 게임 등)사용할 수 있는 것은 다음뿐입니다.
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
Xcode8, iOS11에서 테스트 완료
앱 시작에서 올바른 방향을 얻으려면 체크인을 해야 합니다.viewDidLayoutSubviews(). 여기에 설명된 다른 방법은 작동하지 않습니다.
다음은 그 방법의 예입니다.
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()
}
이것은 앱이 처음 시작할 때, 그리고 앱 실행 중에 회전할 때 항상 작동합니다.
디바이스의 방향을 검출하는 또 다른 방법은 함수 type Collection Did Change(_:)를 사용하는 것입니다.iOS 인터페이스 환경이 변경되면 시스템이 이 메서드를 호출합니다.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
{
super.traitCollectionDidChange(previousTraitCollection)
//...
}
또한 willTransition(to:with:) 함수(attributeCollectionDidChange(_:) 이전 호출)를 사용하여 오리엔테이션 적용 직전에 정보를 얻을 수 있습니다.
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator)
{
super.willTransition(to: newCollection, with: coordinator)
//...
}
앱은 iOS 15에서 실행 중이며 iPhone/iPad에서만 확인했기 때문에 모든 사용 사례에 대해서는 말할 수 없지만 다음 환경 변수를 사용하고 있습니다.
@Environment(\.verticalSizeClass) private var verticalSizeClass
그런 다음 다음 값을 확인합니다.verticalSizeClass == .compact가로 방향verticalSizeClass == .regular세로 방향
https://developer.apple.com/documentation/swiftui/environmentvalues/verticalsizeclass
언급URL : https://stackoverflow.com/questions/38894031/swift-how-to-detect-orientation-changes
'source' 카테고리의 다른 글
| [NSObject description]의 Swift는 무엇입니까? (0) | 2023.04.17 |
|---|---|
| std:: 문자열을 int로 변환하려면 어떻게 해야 하나요? (0) | 2023.04.17 |
| 셀 색상을 얻기 위한 Excel 공식 (0) | 2023.04.17 |
| UITableView, 설정 장소 구분 색상 (0) | 2023.04.17 |
| 컨트롤의 속성을 다른 컨트롤의 속성에 바인딩하려면 어떻게 해야 합니까? (0) | 2023.04.17 |