iOS Device 방향 처리

이원희·2020년 12월 26일
2

📱 iOS

목록 보기
10/24
post-thumbnail

오늘은 화면 회전에 대해 알아보자.

전체 화면 회전

App 전체 화면 회전을 설정하는 방법을 알아보자.

프로젝트 Setting

내가 기존에 알고 있던 App 전반적으로 화면 회전을 제한하는 법은 프로젝트 Setting을 변경해주는 법이다.

위의 사진에서 보이듯 Deployment Info-Device Orientation에서 Portrait, Landscape 옵션을 check할 수 있다.

Deployment Info-Device Orientation에서 옵션을 변경하면 Info.plist파일이 변경되었다는 표시를 확인할 수 있다.

Info.plist

Info.plist 파일을 확인해 보면

위와 같은 옵션들을 확인할 수 있다.
Deployment Info-Device Orientation에서 옵션을 변경하지 않고 Info.plist에서 Supported interface orientations Array를 변경해 설정해줄 수도 있다.

AppDelegate

AppDelegateapplication(_:supportedInterfaceOrientationsFor:) Method를 사용할 수 있다.
해당 MethodApp이 지원하는 방향을 설정할 수 있고, 구현하지 않을시 Info.plist의 지원 방향을 참조한다.

우선 공식 문서에서 해당 Method를 확인해보자.

Discussion을 한 번 확인해볼까요?!

  • MethodApp에서 지원하는 모든 방향 set를 return한다.
  • 특정 View Controller를 회전할지 여부를 결정할 때 이 Method에서 반한 되는 방향에 root view controller 혹은 top view controller에서 지원하는 방향이 포함되어야 한다.

즉, 어떤 view controller를 회전을 결정할때 해당 Method에서 지원하는 방향이 view가 회전하려는 방향을 지원하지 않으면 회전할 수 없다는 말이다.

Method가 App의 가장 상위 view의 방향을 제어한다.

코드로 한 번 확인해보자.


Info.plist: [portrait, landscape] & AppDelegate: [portrait, landscape]

위의 사진처럼 Info.plistAppDelegate 모두 가로, 세로로 설정해주었다.

가로, 세로 모두 잘 표시되는 것을 확인할 수 있다.


Info.plist: [landscape] & AppDelegate: [portrait, landscape]

이번에는 위의 사진처럼 Info.plist는 가로만 지원하고, AppDelegate는 가로, 세로를 지원하도록 설정해주었다.

Info.plist는 가로만 지원하도록 설정했는데 세로 화면에서도 잘 나오는 모습을 확인할 수 있다.

application(_:supportedInterfaceOrientationsFor:)의 Discussion 중

MethodApp이 지원하는 방향을 설정할 수 있고, 구현하지 않을시 Info.plist의 지원 방향을 참조한다.

라는 부분이 있었다.

우리가 Info.plist에서 가로만 지원하도록 설정해뒀지만application(_:supportedInterfaceOrientationsFor:)에서 가로, 세로 모두를 지원하도록 return하고 있기 때문에 가로, 세로 모두에서 화면이 잘 나오고 있다.

만약 우리가 application(_:supportedInterfaceOrientationsFor:)를 따로 구현하지 않았다면 Info.plist의 Orientation을 따랐을 것이다.


Info.plist: [portrait, landscape] & AppDelegate: [landscape]

이번에는 위의 사진처럼 Info.plist는 가로, 세로를 지원하고, AppDelegate는 가로만 지원하도록 설정해주었다.

가로화면만 제대로 출력되는 것을 확인할 수 있다.


Info.plist: [portrait] & AppDelegate: [landscape]

마지막으로 위의 사진처럼 Info.plist는 세로만 지원하고, AppDelegate는 가로만 지원하도록 설정해주었다.

가로화면만 제대로 출력되는 것을 확인할 수 있다.

특정 화면에서 회전을 제한해보자.

그렇다면 이제 app의 전반적인 화면 회전을 설정하는 것이 아닌 특정 화면에 한정해서 회전을 제한해보자.
아래의 내용은 NavigationController를 사용해서 내용을 알아보지만 아래의 내용을 익히면 Modal에도 적용할 수 있을 것이다.

AppDelegate

우리는 AppDelegate의 application(_:supportedInterfaceOrientationsFor:) Method로 App의 가장 상위 view의 방향을 제어할 수 있음을 알고 있다.

이를 이용해서 제어해보자!

  • AppDelegatechangeOrientation: Bool 변수를 선언했다.
  • 해당 변수가 true라면 어떤 방향이라도 대응할 수 있고, false라면 가로 방향만 가능하도록 설정했다.

첫번째 viewController는 첫번째 화면에서는 세로 방향만 가능하도록 viewWillAppearchangeOrientationfalse로 설정했다.
두번째 viewController에서는 모든 방향에 대응하도록 viewWillDisappearchangeOrientationtrue로 설정해줬다.


우리가 원하는 대로 회전을 제어하고 있는 것을 확인할 수 있다.

Q.viewDidLoad에서 changeOrientation을 변경하지 않은 이유는?
처음 첫번째 view -> 두번째 view로 이동할때에는 우리가 의도한대로 회전을 제어할 수 있다.
두번째 view -> 첫번째 view돌아온 후에는 첫번째 view에서 회전이 제어되지 않는다.
(view Life Cycle에 대해 읽고 오면 도움이 된다.)
두번째 viewController가 메모리에 올라간 뒤에는 changeOrientation이 true로 설정된다.
첫번째 viewController로 돌아올때는 viewDidLoad가 다시 호출되지 않으므로 changeOrientation가 false로 설정되지 않는다.


AppDelegate를 가져다 쓰는건 뭔가 Cool하지 않은데?!

AppDelegate를 가져다 쓰는걸 최소화하고 싶었고, 뭔가 Cool해보이지 않아서 다른 방법을 찾아봤다.

supportedInterfaceOrientations Property

AppDelegate에는 application(_:supportedInterfaceOrientationsFor:)라는 Method가 있고,
UIViewController에는 supportedInterfaceOrientations라는 Property가 있다.

공식문서를 확인해보자!

  • view controller가 지원하는 방향을 의미하는 instance property이다.
  • 기기의 방향이 바뀔때 root view controller 혹은 최상위에 modal view controller에서 method를 호출한다고 나와 있다.
  • methodshouldAutorotate가 true 값을 반환할 때만 호출된다.
  • method에서 지원하는 방향이 App 전체적 지원 방향에 들어가 있다면 그 방향으로 회전이 가능하다.

property override

흠... 그럼 view controller마다 지원한느 방향을 설정할 수 있다니까 저 프로퍼티만 override하면 되겠네?!

확인해보자.

위의 코드처럼 첫번째 view controller에서 세로 방향만 지원하도록supportedInterfaceOrientationsoverride했다.

오잉?!
나는 세로 방향만 지원하도록 설정하고 싶었는데 세로, 가로 모두 지원되고 있다.

해당 propertyoverride할때 주의?중요?한 점이 있다.

  • 우리가 override하고 있는 view controller상위 view controller가 있다면 상위 view controllerporperty를 따른다.
  • UINavigationControllerall이라면 그 안에 있는 viewController들은 UINavigationController를 따라 all이 된다.

그럼 어떻게 처리할 수 있을까?

나는 다음과 같은 방법으로 처리했다.

  1. UINavigationController를 상속받는 class를 만들어준다.

    class에서 supportedInterfaceOrientationsoverride해준다.
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return self.topViewController!.supportedInterfaceOrientations
    }

NavigationController의 가장 최상위 viewController(self.topViewController)의 supportedInterfaceOrientations 속성을 return하도록 한다.

  1. 첫번째 view controllersupportedInterfaceOrientationsoverride해준다.

    첫번째 view controller는 세로만 지원한다.
  1. 두번째 view controllersupportedInterfaceOrientationsoverride해준다.

    두번째 view controller는 모든 방향을 지원한다.

좀 더 깔끔하게 처리할 수 있을까?

main view controllersecond view controlelr에서 각각 override 해주던 supportedInterfaceOrientationsUINavigationController에서만 관리해주도록 이렇게 코드를 바꿀 수 있을거 같다.


결과


마무리

오늘은 특정 화면에 대해서 기기 방향을 어떻게 제어할지에 대해 알아봤다.
AppDelegate를 이용한 첫 번째 방법이 좀 덜 번거로운 느낌이었지만 뭔가 이렇게 제어하면 안될거 같은데...? 라는 생각이 들었다.
처음에는 UIViewController에 기기 방향에 관련한 프로퍼티가 있는 것을 확인했는데 왜 제대로 동작을 안하지..? 했는데 UINavigationController에서는 추가로 생각해줘야하는게 있었다.
이를 이해하니 마지막 방법처럼 적용할 수 있었다.
오늘도 포스팅이 오래걸렸지만 재밌었다!
그럼 다음에는 더 흥미진진한 것으로 돌아올테니 오늘은 이만👋

1개의 댓글

comment-user-thumbnail
2024년 7월 4일

안녕하세요. iOS 관련해서 질문이 있습니다.
화면 회전의 의미가 강제로 화면이 회전하는것 일까요? 디바이스의 방향과 상관없이 특정씬이나 특정 함수 호출시 화면 회전이 이뤄지는 함수인가요?

답글 달기