티스토리 뷰
UIView의 경우 익히 알려진 방법들로 스크린샷을 촬영할 수 있다.
extension UIView {
func snapshot() -> UIImage {
let renderer = UIGraphicsImageRenderer(size: bounds.size)
return renderer.image { context in
drawHierarchy(in: bounds, afterScreenUpdates: true)
}
}
}
SwiftUI의 View 타입은 UIView와 다르게 업데이트 시마다 이니셜라이즈된다. 뷰의 렌더된 이미지나 속성을 가지지 않고 UIView를 업데이트해주는 빌더라고 할 수 있다. 그래서 스크린샷 등 렌더링된 이미지를 구하려면 UIKit의 도움을 받아야 한다.
View 타입을 즉시 렌더링하여 저장하기
extension View {
func snapshot() -> UIImage? {
// 1
let hostingController = UIHostingController(rootView: self.ignoresSafeArea())
guard let view = hostingController.view else { return nil }
// 2
let targetSize = view.intrinsicContentSize
view.bounds = CGRect(origin: .zero, size: targetSize)
view.backgroundColor = .clear
// 3
let rederer = UIGraphicsImageRenderer(size: targetSize)
return rederer.image { context in
view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
}
}
}
- UIHostingController를 사용해 View 타입을 UIViewController로 변환하고 view를 가져온다.
- 뷰가 그려질 사이즈인 intrinsicContentSize에 접근해 사이즈를 가져온다.
- 뷰를 크기에 맞게 렌더링하고 이미지를 가져온다.
struct ContentView: View {
private var viewForSnapshot: some View {
Text("스크린샷 찍을 뷰")
}
var body: some View {
VStack {
viewForSnapshot
Button("촬영") {
text.snapshot()
}
}
}
}
이 방법을 사용하면 상위 뷰에서 하위 뷰를 프로퍼티로 저장해놓고 snapshot()을 호출하여 스크린샷을 촬영할 수 있다. 그러나 스스로 크기가 정해지는 뷰(예: 텍스트 등)가 아니면 제대로 작동하지 않는다.
상위 뷰에 의해 크기가 결정되는 뷰의 경우는 실제 렌더링된 UIView 객체를 참조해야 스크린샷을 찍을 수 있다.
Introspect로 UIViewController 가져오기
Introspect라는 오픈소스 라이브러리를 이용하면 손쉽게 기존 UIKit 뷰를 가져와 사용할 수 있다.
Text("스크린샷 찍을 뷰")
.introspectViewController { viewController in
viewForSnapshot = viewController.view
}
UIView를 가져와 저장했다면 UIView의 스크린샷 촬영 메소드를 호출해 촬영을 하면 된다.
'가이드' 카테고리의 다른 글
| iOS에서 이미지/동영상 Orientation 정보 읽고 적용하기 (0) | 2022.08.10 |
|---|---|
| 네이버 지도 SDK 줌 레벨 알아보기 (0) | 2022.07.30 |
| SwiftUI에서 구글로그인 띄우기 (0) | 2022.07.30 |
| SwiftUI 프로젝트에서 커스텀 Scheme 또는 파일 연결 처리하기 (0) | 2022.04.13 |
| SwiftUI 커스텀 바인딩 활용하기 (0) | 2022.04.13 |
