SwiftUI : Preview 레이아웃을 미리 보는방법
Preview
에 대해 알아보도록 합시다.
Preview 동작 과정
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
- 현재 소스 에디터에
PreviewProvider
프로토콜을 준수하는 타입이 존재하는지 확인.PreviewProivder
프로토콜의 필수 구현 사항인previews
타입 프로퍼티에서 뷰 생성.- 액티브 스킬의 목적지로 선택한 시뮬레이터 또는 맥에 연결한 기기의 형태로
preview container
렌더링.- 리뷰 컨테이너를 직접 지정해 줄 경우 3번 에서 선택한 기기를 무시하고 해당 기기 형태로 렌더링.
따라서 가장 먼저 현재 소스 에디터 상에 띄워진 파일에 PreviewProvider
프로토콜을 준수하는 타입이 있어야 합니다. 기존 Swift
에서 사용하던 시뮬레이터에 비해 Preview
는 아주 빠르고 편하게 보여 줍니다.
자동 Privew 갱신
Preview
를 활용하다 보면 언제든 빌드를 다시 하지 않아도 수정 결과가 자동으로 반영됩니다. 하지만 어떤 경우에는 수동으로 갱신해 주어야 하는 경우가 있죠
이 메세지를 읽어보면 자동 갱신 기능은 Preview
의 대상이 되는 파일이 수정되어 모듈을 다시 빌드해야 하는 상황에서 중단된다고 나와있습니다. 그럼 이렇게 모듈을 다시 빌드해야 하는 상황은 언제일까요?
- 프로퍼티와 메서드를 추가 / 제거 / 수정하는 경우
- 저장 프로퍼티의 값 변경
- 뷰의 타입 이름을 변경하거나 또 다른 뷰를 추가할 때
- 앱을 수동으로 빌드하는 경우
위에 상황을 모두 기억할 수 없으니 좀 더 일반화하면 이렇습니다.
파일의 탑 레벨이나 구조체 / 클래스의 구현 범위에서는 키워드, 속성, 프리프로세서 구문에 대한 수정 같은 일부 예외를 제외하면 어떠한 작은 변화라도 일어나는 순간에 자동 갱신이 중단됩니다. 해당 범위 내에서는 한 글자라도 입력 / 삭제 하거나 개행 또는 공백을 추가하면 다시 빌드를 해야 하는 상황이 생깁니다.
Privew 수식어 살펴보기
Xcode
의SwiftUI Pireview
를 사용하면 .previewDevice()
수정자를 사용하여 동시에 여러 화면 크기로 디자인을 보여줄 수 있습니다.
아이폰은 실제로 기기를 모두 보유하고 있지 않아도 다양한 환경에서 점검할 수 있도록 시뮬레이터를 제공하듯이, Preview
에서도 마찬가지로 각 기기별로 preview container
로 지정하여 확인할 수 있는 기능을 제공합니다.
지원되는 장치 목록
<hide/>
/// "Mac"
/// "iPhone 7"
/// "iPhone 7 Plus"
/// "iPhone 8"
/// "iPhone 8 Plus"
/// "iPhone SE"
/// "iPhone X"
/// "iPhone Xs"
/// "iPhone Xs Max"
/// "iPhone Xʀ"
/// "iPad mini 4"
/// "iPad Air 2"
/// "iPad Pro (9.7-inch)"
/// "iPad Pro (12.9-inch)"
/// "iPad (5th generation)"
/// "iPad Pro (12.9-inch) (2nd generation)"
/// "iPad Pro (10.5-inch)"
/// "iPad (6th generation)"
/// "iPad Pro (11-inch)"
/// "iPad Pro (12.9-inch) (3rd generation)"
/// "iPad mini (5th generation)"
/// "iPad Air (3rd generation)"
/// "Apple TV"
/// "Apple TV 4K"
/// "Apple TV 4K (at 1080p)"
/// "Apple Watch Series 2 - 38mm"
/// "Apple Watch Series 2 - 42mm"
/// "Apple Watch Series 3 - 38mm"
/// "Apple Watch Series 3 - 42mm"
/// "Apple Watch Series 4 - 40mm"
/// "Apple Watch Series 4 - 44mm"
Xcode
의 대상 메뉴에 표시되는 장치의 정확한 이름 (ex : "iPhone 12
") 과 함께 제공되어야 합니다.
모델명 외에 모델 넘버를 이용해서 지정하는 것도 가능하며, 목록에 없는 최신모델도 문제없이 사용이 가능합니다.
ContentView()
.previewDevice(PreviewDevice(rawValue: "iPhone 12 Pro Max"))
Preview
하기 위해 특정 장치를 사용할 때 .previewDisplayName()
수정자를 추가하는 것이 유용합니다. 그러면 미리 보기 창에서 장치 위에 어떤 기기로 미리보기 되고 있는지 볼 수 있습니다.
ContentView()
.previewDevice(PreviewDevice(rawValue: "iPhone XS"))
.previewDisplayName("iPhone XS")
기기를 지정하여 여러 디바이스 표시
Group
을 사용하여 여러 기기를 Preview
할 수 도 있습니다.
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
Group {
ContentView()
.previewDevice(PreviewDevice(rawValue: "iPhone XS"))
.previewDisplayName("iPhone XS")
ContentView()
.previewDevice(PreviewDevice(rawValue: "iPhone 8"))
.previewDisplayName("iPhone 8")
}
}
}
또, 뷰는 동일한 구성으로 하되 다양한 preview container
를 사용해 동시에 출력하고 싶다면 ForEach
를 이용하는것이 편리합니다.
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ForEach(["iPhone 12 Pro", "iPhone 8"], id: \.self) {
ContentView()
.previewDevice(PreviewDevice(rawValue: $0))
}
}
}
각 preview container
마다 이름을 지정해줄 수 도 있습니다.
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ForEach(["iPhone 12 Pro", "iPhone 8"], id: \.self) {
ContentView()
.previewDevice(PreviewDevice(rawValue: $0))
.previewDisplayName($0) //각 프리뷰 컨테이너 이름지정
}
}
}
레이아웃 변경하기
이번에는 아래 그림처럼 작은 크기의 뷰를 Preview
로 확인해야 한다고 예를 들어보겠습니다.
이때는 실제 나타내어야 할 뷰보다 preview container
의 크기가 많이 크기 때문에 뷰의 크기에 맞게 또는 특정 크기로 지정하여 보고 싶은 경우도 있죠? 그럼 previewLayout
수식어를 이용해 preview container
의 크기를 변경할 수 있습니다. 이 수식어는 previewLayout
열거형 타입의 값을 전달받으며 이 타입은 현재 3
가지 선택지를 제공하고 있습니다.
구분 | 설명 |
device | 기본값. 컨테이너가 기기 본래의 크기와 형태로 나타납니다. |
sizeThatFits | 컨테이너를 프리뷰의 크기에 맞춰서 유동적으로 조절합니다. |
fixed(width: height:) | 지정한 너비와 높이에 맞춰서 컨테이너의 크기를 고정합니다. |
기본값은 패스하고 sizeThatFits
와 fixed
값을 지정해서 어떻게 변화하는지 살펴보겠습니다.
SizeThatFits
ContentView()
.previewLayout(.sizeThatFits)
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ForEach(["iPhone 12 Pro", "iPhone 8"], id: \.self) {
ContentView()
.previewLayout(.sizeThatFits)
.previewDevice(PreviewDevice(rawValue: $0))
.previewDisplayName($0) //각 프리뷰 컨테이너 이름지정
}
}
}
sizeThatFits
는 뷰가 가진 크기와 컨테이너 크기가 일치하는 것을 볼 수 있습니다. 이것은 단지 작게 보는 것뿐만 아니라 화면 크기를 넘어서는 큰 뷰를 만들 때도 활용 할 수 있는데, 뷰의 크기가 기기의 크기보다 크더라도 Preview
가 그것에 맞게 늘어나 전체 모습을 보면서 작업할 수 있습니다.
Fixed
ContentView()
.previewLayout(.fixed(width: 350, height: 250))
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ForEach(["iPhone 12 Pro", "iPhone 8"], id: \.self) {
ContentView()
.previewLayout(.fixed(width: 350, height: 250))
.previewDevice(PreviewDevice(rawValue: $0))
.previewDisplayName($0) //각 프리뷰 컨테이너 이름지정
}
}
}
fixed
는 preview container
의 크기를 고정하고자 할 때 사용합니다. 결과 화면에서도 뷰의 크기와 무관하게 컨테이너의 크기가 지정한 값으로 고정된 것을 확인 할 수 있죠. 너무 크거나 작지 않게 일정 공간을 확보한 상태로 확인하고자 할 때 사용하기 좋습니다.
가로모드
또, 아직 Preview
에서는 가로 모드를 별도로 지원하지 않지만, 세로 모드일때의 너비와 높이를 맛바꾸어 입력하게 되면 가로 모드로 뷰를 표현하는 것과 유사한 효과를 낼 수도 있습니다.
예를들어 iPhone 11 Pro Max
의 크기는 414 x 896
포인트 이므로 이것을 반대로 896 x 414
로 지정해주는것이죠. 가로 모드를 지원하는 앱이라면 이런 방법을 많이 활용하게 될 것입니다. :)
ContentView()
.previewLayout(.fixed(width: 896, height: 414))
읽어주셔서 감사합니다🤟