Swift에서 장치 방향 가져 오기


79

Swift에서 현재 장치 방향을 어떻게 얻을 수 있는지 궁금합니다. Objective-C에 대한 예가 있다는 것을 알고 있지만 Swift에서 작동하지 못했습니다.

장치 방향을 가져 와서 if 문에 넣으려고합니다.

이것은 내가 가장 많은 문제를 겪고있는 라인입니다.

[[UIApplication sharedApplication] statusBarOrientation]

당신의 문제는 무엇입니까? 그것을 Swift로 번역하거나 기대하는 값을 얻습니까?
David Rönnqvist

1
기기 방향이 UI 방향과 반드시 ​​일치하지는 않습니다. 케이스 포인트-장치를 평평하게 놓고 코드를 테스트하십시오!
Patrick

답변:


70

당신이 사용할 수있는:

override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
    var text=""
    switch UIDevice.currentDevice().orientation{
    case .Portrait:
        text="Portrait"
    case .PortraitUpsideDown:
        text="PortraitUpsideDown"
    case .LandscapeLeft:
        text="LandscapeLeft"
    case .LandscapeRight:
        text="LandscapeRight"
    default:
        text="Another"
    }
    NSLog("You have moved: \(text)")        
}

SWIFT 3 업데이트

override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
    var text=""
    switch UIDevice.current.orientation{
    case .portrait:
        text="Portrait"
    case .portraitUpsideDown:
        text="PortraitUpsideDown"
    case .landscapeLeft:
        text="LandscapeLeft"
    case .landscapeRight:
        text="LandscapeRight"
    default:
        text="Another"
    }
    NSLog("You have moved: \(text)")        
}

또는

override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
}

알림으로 확인할 수 있습니다. IOS8 Swift : 방향 변경을 감지하는 방법?

참고 : didRotateFromInterfaceOrientation 은 더 이상 사용되지 않습니다. iOS 2.0 이상에서는 viewWillTransitionToSize 사용

Face Up 및 Face Down의 경우 작동하지 않습니다. 따라서 다음을 사용해야합니다.

if UIApplication.shared.statusBarOrientation.isLandscape {
     // activate landscape changes
} else {
     // activate portrait changes
}

공유 해주셔서 감사합니다!
ssowri1

흠 ... 무엇을 이미 회전 후이보기에 사용자를 탐색, 우리는 ... 시작 방향을 알고하지 않는다면
ScottyBlades

이 기능이 더 이상 사용되지 않음에도 불구하고 여전히 사용중인 경우. 구현에서 슈퍼 메서드를 호출하는 것을 잊지 마십시오. 즉 : super.didRotate(from: fromInterfaceOrientation). Apple 문서에서 : "이 메소드의 구현은 실행 중 어느 시점에서 super를 호출해야합니다."
Bocaxica

55

Objective-C 코드와 같은 상태 표시 줄 (및 UI) 방향을 얻으려면 다음과 같이하면됩니다.

UIApplication.sharedApplication().statusBarOrientation

UIDevice 의 orientation속성 을 사용할 수도 있습니다 .

UIDevice.currentDevice().orientation

그러나 이는 UI의 방향과 일치하지 않을 수 있습니다. 문서에서 :

속성 값은 장치의 현재 방향을 나타내는 상수입니다. 이 값은 기기의 물리적 방향을 나타내며 애플리케이션 사용자 인터페이스의 현재 방향과 다를 수 있습니다. 가능한 값에 대한 설명은“UIDeviceOrientation”을 참조하십시오.


UIApplication.sharedApplication (). statusBarOrientation은 주 스레드에만 있습니다
Yair hadad

도와 주셔서 감사합니다!
ssowri1

1
uidevice.current.orientation.isportrait를 사용하여 기기 방향을 확인하고 앱의 UI를 변경했지만 기기를 책상 위에 올려도 변경되었습니다. 하지만 덕분에 이제는 perfactly 잘 작동
걸펌 칸

빠른 5.1 업데이트 -> UIDevice.current.orientation
호나우두 알베르

UIDevice.current.orientation.isPortrait는 장치 방향이 앞면 또는 뒷면 인 경우 작동하지 않습니다. 이 답변과 같은 상태 표시 줄을 확인하는 것은 일관되고 나를 위해 일했습니다.
Austin

26

Apple은 최근에 Landscape vs. Portrait 개념을 없애고 화면 크기를 선호합니다. 그러나 이것은 작동합니다.

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

7
나는 당신의 솔루션과 함께 애플이 "당신의 커스텀 뷰 컨트롤러에서이 메소드를 재정의한다면, 당신의 구현의 어느 시점에서 항상 super를 호출하라"라고
말하고있을

25
struct DeviceInfo {
struct Orientation {
    // indicate current device is in the LandScape orientation
    static var isLandscape: Bool {
        get {
            return UIDevice.current.orientation.isValidInterfaceOrientation
                ? UIDevice.current.orientation.isLandscape
                : UIApplication.shared.statusBarOrientation.isLandscape
        }
    }
    // indicate current device is in the Portrait orientation
    static var isPortrait: Bool {
        get {
            return UIDevice.current.orientation.isValidInterfaceOrientation
                ? UIDevice.current.orientation.isPortrait
                : UIApplication.shared.statusBarOrientation.isPortrait
        }
    }
}}

swift4 답변 : 이것이 내가하는 방법입니다.

1. 모든 종류의 뷰 컨트롤러에서 작동합니다.

2. 사용자가 앱을 회전 할 때도 작동합니다.

3. 또한 처음으로 앱을 설치하십시오.


1
완벽한 대답! 감사합니다
torap

좋지만 @objc 클래스 대신 견인 시간을 쓰는 이유 var isLandscape : Bool {return! isPortrait} 중요한 것을 얻지 못하고 있습니까? ;)
Renetik

나는하지 않습니다으로 와우가 : 정말 감사합니다 .. 완벽하게 작동 것
인 Yogesh 파텔

방향이 변경되었는지 어떻게 알 수 있습니까?
Daniel Springer

14

스위프트 4 :

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

isFlat 오리엔테이션은 어떻습니까?
Michał Ziobro

2
재정의하는 함수의 어느 시점에서 super.viewWillTransition (to : size, with : coordinator)를 호출하는 것을 잊지 마십시오.
Bocaxica

13

현재 장치 방향을 찾으려면 다음 코드를 사용하십시오.

UIApplication.sharedApplication (). statusBarOrientation

신속한 3.0

UIApplication.shared.statusBarOrientation


iPad air 1 & 2가 잘못된 값을 반환하고 iPad 2 및 iPhone이 올 바릅니다. 나는 정말로 모든 장치에서 작동하는 것을 찾으려고 노력하고 있지만 사과가 여기에서 진짜 엉망이되었습니다! :(
Steven B.

달리 UIDevice.current.orientation, UIApplication.shared.statusBarOrientation초기로드에 사용할 수 있으며, 화면이 회전하지 직후.
ewizard

10

을 사용하는 데 문제가 있었지만 InterfaceOrientation로드시 방향에 액세스하지 않는 것을 제외하고는 정상적으로 작동했습니다. 그래서 나는 이것을 시도했고 그것은 골키퍼입니다. 이것은 절대적인 bounds.width방향이 아니라 항상 현재 방향을 참조하기 때문에 작동합니다 nativeBounds.width.

    if UIScreen.mainScreen().bounds.height > UIScreen.mainScreen().bounds.width {
        // do your portrait stuff
    } else {    // in landscape
        // do your landscape stuff
    }

나는 이것을 from willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval)과 from 이라고 부르지 viewDidLoad만 유연합니다.

그 방향의 포인터에 대한 zSprawl에게 감사드립니다. 이것은 iOS 8 이상에서만 유용하다는 점을 지적해야합니다.


iOS 9 및 10 iPad에서는 작동하지 않으며 초기 값만 정확하며 다음 값은 모두 반대 방향입니다.
Steven B.

@ Steven.B Hmmm ... iOS 9의 iPad Air, iPad 3 및 시뮬레이터에서 잘 작동합니다. 베타 테스터와도 작업했습니다. 아마도 이것에 영향을 미치는 다른 코드를 사용하고있을 것입니다.
bpedit 17:09에

이 코드는 아마도 UIViewcontroller에서 사용될 때만 작동 할 것입니다. 사용자 지정 UIView 클래스에서 방향 및 경계를 얻으려고하지만 제가 테스트하는 거의 모든 장치는 방향이 프레임보다 정확하거나 여전히 잘못된 경우 다른 값을 반환합니다.
Steven B.

10

따라서 Apple이 전체 방향 문자열 ( "portrait", "landscape")을 비추천한다면, 당신이 신경 쓰는 것은 너비와 높이의 비율입니다. (@bpedit의 답변과 비슷합니다)

너비를 높이로 나눌 때 결과가 1보다 작 으면 mainScreen 또는 컨테이너 또는 "세로" "모드"에있는 모든 것입니다. 결과가 1보다 크면 "가로"그림입니다. ;)

override func viewWillAppear(animated: Bool) {
    let size: CGSize = UIScreen.mainScreen().bounds.size
    if size.width / size.height > 1 {
        print("landscape")
    } else {
        print("portrait")
    }
}
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    if size.width / size.height > 1 {
        print("landscape")
    } else {
        print("portrait")
    }
}

(이 접근 방식을 사용하면 비율이 정확히 1이고 너비와 높이가 같을 때 조건을 특별히 처리하는 데 관심이 없을 것입니다.)


1
좋은! 답변에 대한 약간의 개선 : 호출하는 것을 잊지 마세요. super.viewWillAppear(animated)그리고 super.viewWillTransition(to: size, with: coordinator)어떤 시점에서 재정의 함수
Bocaxica

8

Swift 3+

원래:

NotificationCenter.default.addObserver(self, selector: #selector(self.didOrientationChange(_:)), name: .UIDeviceOrientationDidChange, object: nil)

@objc func didOrientationChange(_ notification: Notification) {
    //const_pickerBottom.constant = 394
    print("other")
    switch UIDevice.current.orientation {
        case .landscapeLeft, .landscapeRight:
            print("landscape")
        case .portrait, .portraitUpsideDown:
            print("portrait")
        default:
            print("other")
    }
}

:)


나는이 대답을 좋아한다. func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)traitcollection이 항상 width.regular및 이므로 사용할 수없는 iPad와 같은 더 큰 화면에 매우 유용 height.regular하므로 traitCollection이 회전시 변경되지 않습니다. Swift 4에서 알림의 이름이 UIDevice.orientationDidChangeNotification.
Bocaxica

3

Rob의 답변을 기반으로 한 Swift 3

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if (size.width / size.height > 1) {
        print("landscape")
    } else {
        print("portrait")
    }
}

2
전화하는 것을 잊지 마십시오 super.viewWillTransition(to: size, with: coordinator)당신의 재정 기능에 어떤 시점에서
Bocaxica

3

Obj-C 코드에 대한 Swift의 대체 코드가

if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) 

이다

if UIApplication.shared.statusBarOrientation.isLandscape

참고 : 상태 표시 줄 방향이 가로인지 확인하려고합니다. 풍경이라면 if 문은 참입니다.


3

statusBarOrientation더 이상 사용되지 않으므로 이상 위 답변 과 같이 사용할 수 없습니다.

이 코드에서는 감가 상각에 대한 걱정없이 방향을 얻을 수 있습니다. Swift 5 ioS 13.2 100 % 테스트

struct Orientation {
    // indicate current device is in the LandScape orientation
    static var isLandscape: Bool {
        get {
            return UIDevice.current.orientation.isValidInterfaceOrientation
                ? UIDevice.current.orientation.isLandscape
                : (UIApplication.shared.windows.first?.windowScene?.interfaceOrientation.isLandscape)!
        }
    }
    // indicate current device is in the Portrait orientation
    static var isPortrait: Bool {
        get {
            return UIDevice.current.orientation.isValidInterfaceOrientation
                ? UIDevice.current.orientation.isPortrait
                : (UIApplication.shared.windows.first?.windowScene?.interfaceOrientation.isPortrait)!
        }
    }
}

2
   override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
    if (toInterfaceOrientation.isLandscape) {
        NSLog("Landscape");
    }
    else {
        NSLog("Portrait");
    }
}

0

horizontalSizeClass& 사용하십시오 verticalSizeClass:

import SwiftUI

struct DemoView: View {
    
    @Environment(\.horizontalSizeClass) var hSizeClass
    @Environment(\.verticalSizeClass) var vSizeClass
    
    var body: some View {
        VStack {
            if hSizeClass == .compact && vSizeClass == .regular {
                VStack {
                    Text("Vertical View")
                }
            } else {
                HStack {
                    Text("Horizontal View")
                }
            }
        }
    }
}

튜토리얼 에서 찾았습니다 . 관련 Apple 문서 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.