(image 땡스투 위키피디아입니다.)
오늘은 UI Orientation을 가로모드로, 세로모드로 강제하는 방법에 대해 알아볼텐데요,
앱 전체를 가로, 세로로 바꾸는건 너무나 쉽지만,
특정 뷰만 가로로, 세로로 바꾸는건 좀 까다로워 보입니다.
그리고 우선 iOS 16부터 방법이 바뀌었습니다.
여러분 버전 대응하십셔!
🍎: orientation 강제 권하지 않는다(지만 어떡해 해야지)
view Will Apear 시점에 선언해야 잘 바뀐답니다.
private func forcePortraitOrientation() {
if #available(iOS 16.0, *) {
let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait))
} else {
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
}
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
override var shouldAutorotate: Bool {
return true
}
private func forceLandscapeOrientation() {
if #available(iOS 16.0, *) {
let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: .landscapeRight))
} else {
let value = UIInterfaceOrientation.landscapeRight.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
}
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .landscape
}
override var shouldAutorotate: Bool {
return true
}
shouldAutorotate 값을 바꾸면 디바이스 가로로 눕히거나 세로로 돌리면, 화면이 고정되거나 풀리거나의 여부를 관리할 수 있겠지?? 라고 생각했는데요,
-> 3일 뒤 아니라는 것을 꺠달아서 글을 더 첨부합니다.
안되더라구요, 강제..
그러니깐 핸드폰을 가로로 눕히면 가로모드로 잘 나옵니다. 근데 이제 세로로 세우면 UI 가 깨지고 세로로 바뀌어버려요.
문제에 대한 원인분석을 엄청나게 해봤는데,
일단 저는 어떤 뷰는 세로로, 어떤 뷰는 가로로 강제해야 하는 상황이었습니다.
핸드폰 화면 가로, 세로 모드(orientation)에 대해 관여할 수 있는게 뭐가 있을까 나열해봤더니,
1) 아이폰 기본 설정(화면 회전 허용 여부)
2) AppDelegate, SceneDelegate에서 앱 전체에 대한 설정
3) info.plist에서 앱 전체에 대한 설정
4) 뷰별로 위에 써놓은 코드로 관리
이 정도가 있는데, 문제는 얘네가 충돌하면 4번이 무시될 확률이 높다.(3일 전에 쓴 윗 글 내용이죠) ㅎ하하. 실제로 무시당했습니다.
게다가 4번도 뷰들이 NavigationController로 연결되어있는 경우, 상위뷰에서 하위뷰에 대한 영향을 끼칠 가능성도 있구요.
하
그래서 일단은 어떻게 해결했냐면요,
AppDelegate에는 우선은 세로모드로 강제해두고,
AppDelegate에다가 앱 전체에 대한 전역변수를 선언해서,
var shouldSupportLandscapeOrientation = false
가로모드로 강제해야 하는 뷰에서 이 전역변수를 가져다가 앱 전체에 대한 화면 모드를 바꿔버립니다.
// viewController에서
let appDelegate = UIApplication.shared.delegate as! AppDelegate
override func viewWillAppear(_ animated: Bool) {
appDelegate.shouldSupportLandscapeOrientation = true
}
그리고 가로->세로로 돌아가야 하는 시점에는, 가로모드의 마지막 뷰에서 viewWillDisappear 시점에 다시 appdelegate의 전역변수를 다시 true로 바꿔주었습니다.
이렇게 하면 되긴 됩니다.ㅎ
임시방편인거같지만 더 좋은 방법 있으면 알려주세요 제발~
그리고 혹시 SwiftUI로도 특정 뷰만 가로모드 강제할 수 있나요? 이 부분도 아신다면 알려주세요 제발~ 🥕🥕🥕🥕🥕
SwiftUI로도 Custom AppDelegate, SceneDelegate쓸 수 있어요. 거기서 뽑아내고 onAppear 시점에 appDelegate.shouldSupportLandscapeOrientation = true 하면 될거같아요