SwiftUI 관련 팁

2022년 10월 31일 수정

View의 프로퍼티 값 저장하고 불러오기

원하는 프로퍼티에 @SceneStorage 를 붙여주면 앱 재실행 시의 상태를 복구할 수 있다.

@SceneStorage("myProperty") var myProperty: String?

@SceneStorage 는 장면(Scene) 단위로 저장된다. 그 외에 State와 동작이 유사해서 대체도 가능하다.

print 디버그 로그

View의 body 프로퍼티 처럼 some View 를 생성하는 코드 안에선 print 함수 코드는 컴파일 에러가 발생하기 때문에 사용할 수가 없다. 대신 약간 돌려서 사용하는 방법이 있다.

let _ = print("some log")

위 코드는 View의 body를 리턴하는 코드 내에서도 문제없이 빌드되고 의도대로 동작한다.

기존 컴포넌트 붙이기

SwiftUI가 도입되기 전에 사용하던 컴포넌트를 SwiftUI 뷰에 붙이는 방법이다. 아래는 MKMapView를 SwiftUI 형태로 감싸는 예제다.

struct MapView: UIViewRepresentable {
    var coordinate: CLLocationCoordinate2D

    func makeUIView(context: Context) -> MKMapView {
        MKMapView(frame: .zero)
    }

    func updateUIView(_ view: MKMapView, context: Context) {
        let span = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
        let region = MKCoordinateRegion(center: coordinate, span: span)
        view.setRegion(region, animated: true)
    }
}

이런 식으로 코딩해 놓으면 SwiftUI 코드들과 조화를 이룰 수 있다.

Xcode 미리보기 관련

풀스크린 뷰(iOS)

struct ContentView: View {
    var body: some View {
        Text("Fullscreen Text View")
            .edgesIgnoringSafeArea(.all)
    }
}

edgesIgnoringSafeArea 속성으로 안전 영역을 몽땅 덮어버리면 바로 풀스크린 뷰다.

다크 테마 미리보기

struct SampleView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            SampleView()
                .environment(\.colorScheme, .dark)
        }
    }
}

미리보기(Preview) 크기 조절하기

struct SampleView_Previews: PreviewProvider {
    static var previews: some View {
        SampleView()
            .previewLayout(.fixed(width: 500, height: 300))
    }
}

멀티 미리보기(preview)

하나의 뷰 코드를 여러 데이터를 이용해 보기 위해서 아래와 같은 미리보기 코드를 작성할 수 있다.

struct SampleView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            SampleView(data: someData[0])
                .previewLayout(.fixed(width: 300, height: 100))
            SampleView(data: someData[1])
                .previewLayout(.fixed(width: 300, height: 100))
        }
    }
}

각각의 뷰 사이즈가 동일하다면 아래 처럼 묶을 수도 있다.

struct SampleView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            SampleView(data: someData[0])
            SampleView(data: someData[1])
        }
        .previewLayout(.fixed(width: 300, height: 100))
    }
}

밝은 모드나 다크 모드 시의 차이를 한 번에 볼 때도 유용하다.

struct SampleView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            SampleView()
                .environment(\.colorScheme, .light)
            SampleView()
                .environment(\.colorScheme, .dark)
        }
    }
}

디바이스 별 미리보기

아래는 특정 디바이스 크기로 미리보기를 볼 수 있는 코드다.

struct SampleView_Previews: PreviewProvider {
    static var previews: some View {
        SomeView()
            .previewDevice(PreviewDevice(rawValue: "iPhone SE"))
    }
}

물론 멀티 디바이스 미리보기도 가능하다.

struct SampleView_Previews: PreviewProvider {
    static var previews: some View {
        SomeView()
            .previewDevice(PreviewDevice(rawValue: "iPhone SE"))
        SomeView()
            .previewDevice(PreviewDevice(rawValue: "iPhone XS Max"))
    }
}

디바이스가 많으면 ForEach로 묶어버릴 수도 있다. 기왕 하는거 프리뷰 밑에 이름도 붙여서 구분해 보자.

struct SampleView_Previews: PreviewProvider {
    static var previews: some View {
        ForEach(["iPhone SE", "iPhone XS", "iPhone XS Max"], id: \.self) {
            deviceName in
            SomeView()
                .previewDevice(PreviewDevice(rawValue: deviceName))
                .previewDisplayName(deviceName)
        }
    }
}

가로모드(landscape) 미리보기

가로모드로 뷰를 보기 위해 프리뷰 코드에 원하는 뷰를 아래와 같은 식으로 코딩할 수 있다.

SomeView().previewInterfaceOrientation(.landscapeRight)

참고로 previewInterfaceOrientation() 메서드는 iOS 15부터 사용 가능하다.