보통 아이폰은 안드로이드보다 OS나 화면 크기에서 파편화가 덜한 편입니다. 제조사가 애플 단 하나기 때문이죠. 하지만 iOS 디바이스도 이제는 화면 크기가 정말로 다양해졌습니다. Human Interface Guideline에서 들고 있는 디바이스 종류만 16종에 달할 정도죠.
실제로 저 픽셀 사이즈를 그대로 이용하는 것은 아닙니다. 기기에 따라 미리 정해진 인자에 따라 실제 개발자가 사용하는 단위로 변형이 일어납니다.
예를들어 Scalar factor가 x2인 12.9” iPad Pro에서의 1px는 실제 기기에서의 2px에 해당하고, x3인 iPhone XS에서의 1px는 실제 기기에서의 3px에 해당합니다.
이렇게 디바이스를 세세하게 나누어서 코딩할 수도 있지만, 여간 번거로운 게 아닙니다. 게다가 디바이스가 하나 늘어날 때마다 코드를 추가해줘야만 하는 문제도 있고요
기기를 일일이 체크하는 대신, 특정 기준에 따라 카테고리를 만들어서 분류한 뒤 해당 카테고리에 일률적인 기준을 적용해준다면 어떨까요? 새로운 디바이스가 나와도 해당 카테고리 내에 있다면 새로 코드를 짜지 않아도 어느 정도는 대응이 가능할 것 입니다.
이러한 일을 가능하게 하기 위해 애플에서는 Size Class라는 것을 만들어 두었습니다. 프로그램 상에서는 UITraitCollection 이라는 클래스로 표현되고, UITraitEnvironment 프로토콜을 채택한 클래스의 traitCollection 프로퍼티로 참조가 가능힙니다. 해당 클래스로는 UIScreen, UIWindow, UIViewController, UIPresentationController, UIView 가 있습니다.
traitCollection 프로퍼티는 화면 사이즈 말고도 다양한 정보를 담고 있습니다. 자세한 것은 UITraitCollection 공식 문서를 참조해주세요.
traitCollection의 여러 프로퍼티 중 오늘 주목할 것은 horizontalSizeClass와 verticalSizeClass입니다. 각각 가로, 세로의 size Class를 나타내는 것으로, 현재 기기의 사이즈 클래스를 해당 프로퍼티들을 참조해서 확인할 수 있습니다.
사이즈 클래스는 regular, compact로 나뉘며 기기의 종류와 현재 방향에 따라 값이 바뀝니다.
기기별로 어떤 사이즈 클래스를 가지는 지는 다음 표와 같습니다.
복잡해 보이지만 다음과 같은 규칙을 찾을 수 있습니다.
-
iPad계열 : portrait, landscape에 상관 없이 언제나 (Regular,Regular)입니다.
-
iPhone 계열 : portrait 상태에서는 언제나 (Compact, Regular) 입니다. landscape 상황에서는 기종에 따라 나뉩니다.
-
Plus,Max,XR : (Regular, Compact) 입니다.
-
일반 사이즈 : (Compact, Compact) 입니다.
-
이를 이용하여 현재 디바이스의 종류를 간단하게 체크할 수 있는 유틸리티 클래스를 만들 수 있습니다.
// 아이폰과 아이패드를 구분하기 위한 클래스
class DeviceChecker {
static func isIPad() -> Bool {
let traitCollection = UIScreen.main.traitCollection
return traitCollection.horizontalSizeClass == .regular && traitCollection.verticalSizeClass == .regular
}
static func isIPhone() -> Bool {
return !isIPad()
}
}
이를 이용해서 UI 배치를 상황에 맞게 적절히 해낼 수 있습니다.