-
Swift iOS: 디바이스 자체 설정에 방향 락이 걸려있을 때도 인식하게 하는 법공부/Swift(프로그래밍 언어) 2026. 3. 23. 02:45반응형사용자가 제어 센터에서 '세로 방향 고정(Orientation Lock)'을 켜두면, 시스템 수준의 UIDevice.orientationDidChangeNotification이나 viewWillTransition은 더 이상 동작하지 않습니다.
이럴 때는 소프트웨어적인 신호가 아닌, 기기의 물리적 센서(가속도계, 자이로스코프) 데이터를 직접 읽어오는 Core Motion 프레임워크를 사용해야 합니다. 센서는 소프트웨어 잠금 여부와 상관없이 기기의 기울기를 항상 감지하기 때문입니다.Core Motion을 이용한 감지 방법 (Swift)
CMMotionManager를 사용해 기기의 가속도 값을 받아온 뒤, x축과 y축의 비중을 계산하여 물리적인 방향을 판별할 수 있습니다.import CoreMotion class OrientationManager { let motionManager = CMMotionManager() func startDeviceMotionUpdates() { // 센서 업데이트 주기 설정 (예: 초당 10회) motionManager.deviceMotionUpdateInterval = 0.1 if motionManager.isDeviceMotionAvailable { motionManager.startDeviceMotionUpdates(to: .main) { (motion, error) in guard let acceleration = motion?.gravity else { return } // 가속도 센서 값(gravity)으로 방향 계산 // x: 가로축, y: 세로축 (-1.0 ~ 1.0) let x = acceleration.x let y = acceleration.y if abs(y) > abs(x) { if y > 0 { print("물리적 방향: Portrait Upside Down") } else { print("물리적 방향: Portrait") } } else { if x > 0 { print("물리적 방향: Landscape Right") } else { print("물리적 방향: Landscape Left") } } } } } func stopUpdates() { motionManager.stopDeviceMotionUpdates() } }구현 시 고려사항
- 배터리 소모: 하드웨어 센서를 계속 사용하므로, 방향 감지가 필요한 화면(예: 카메라, 비디오 플레이어)에서만 활성화하고 나머지는 stopDeviceMotionUpdates()로 꺼주는 것이 중요합니다.
- 정밀도 설정: 위 예시는 간단한 중력 가속도(g) 기준입니다. 더 정밀한 각도가 필요하다면 motion.attitude의 Roll이나 Pitch 값을 활용할 수 있습니다.
- 사용 예시: 유튜브 앱의 경우, 방향 잠금이 켜져 있어도 전체 화면 버튼을 누르거나 기기를 돌릴 때 Core Motion 데이터를 참고하여 레이아웃 변경을 제안하기도 합니다.
[추가] 클로저를 추가하여 외부에서 방향에 따른 작업 수행하기
디바이스 방향에 대한 enum을 추가합니다.enum DeviceOrientation { case portrait case portraitUpsideDown case landscapeLeft case landscapeRight }OrientationManager의 멤버 변수로 다음을 추가합니다.
var onOrientationChanged: ((DeviceOrientation) -> Void)?startDeviceMotionUpdates() 함수 내부 if문을 다음과 같이 변경합니다.
if motionManager.isDeviceMotionAvailable { // 👇 추가 motionManager.startDeviceMotionUpdates(to: .main) { [weak self] (motion, error) in guard let acceleration = motion?.gravity else { return } // 가속도 센서 값(gravity)으로 방향 계산 // x: 가로축, y: 세로축 (-1.0 ~ 1.0) let x = acceleration.x let y = acceleration.y let orientation: DeviceOrientation // 👈 추가 if abs(y) > abs(x) { if y > 0 { // print("물리적 방향: Portrait Upside Down") orientation = .portraitUpsideDown } else { // print("물리적 방향: Portrait") orientation = .portrait } } else { if x > 0 { // print("물리적 방향: Landscape Right") orientation = .landscapeRight } else { // print("물리적 방향: Landscape Left") orientation = .landscapeLeft } } self?.onOrientationChanged?(orientation) // 👈 추가 } }외부 뷰 컨트롤러 등에서 사용합니다. (예: UIKit 에서 버튼 방향을 오리엔테이션에 따라 변경)
private func setupOrientationManager() { orientationManager.startDeviceMotionUpdates() orientationManager.onOrientationChanged = { [weak self] orientation in guard let self else { return } self.currentOrientation = orientation let angle: CGFloat switch orientation { case .portrait: angle = 0 case .portraitUpsideDown: angle = .pi case .landscapeLeft: // 중력 기반 방향 판단이 UIKit 좌표계와 반대로 해석되는 경우 // angle = -.pi / 2 // 이론상 angle = .pi / 2 // 실제 case .landscapeRight: // 중력 기반 방향 판단이 UIKit 좌표계와 반대로 해석되는 경우 // angle = .pi / 2 // 이론상 angle = -.pi / 2 } UIView.animate(withDuration: 0.2) { self.doneButton.transform = CGAffineTransform(rotationAngle: angle) self.cancelButton.transform = CGAffineTransform(rotationAngle: angle) self.thumbnailContainer.transform = CGAffineTransform(rotationAngle: angle) } } }반응형'공부 > Swift(프로그래밍 언어)' 카테고리의 다른 글
Embedded Swift: ESP32-C6을 Wifi에 연결시켜 웹 서버로 사용하기, 브라우저에서 LED 제어 (0) 2026.03.31 Embedded Swift 설치, 코드 작성, ESP32-C6에서 빌드 및 작동시키는 방법 (0) 2026.03.21 Swift iOS 프로젝트에서 경고창(얼럿)을 띄우는 방법 정리 (기본 방식 vs 라이브러리) (0) 2026.03.05 CocoaPods 서비스 종료? 2026년 이후 변화와 개발자가 알아야 할 점 (0) 2026.02.23 iOS Swift: 위젯(Widget) 넣기 (난이도: 어려움) (0) 2026.02.15