UIViewController를 SwiftUI와 통합하기
UIViewController와 SwiftUI
UIView 통합: 개별 또는 소규모 의 UIKit 기반 컴포넌트를 SwiftUI와 통합하는데 유용
UIViewController 통합: 전체 뷰 컨트롤러 인스턴스를 통합
- UIViewControllerRepresentable 프로토콜 사용
- UIViewRepresentable 프로토콜과 유사
UIImagePickerController 통합하기
UIImagePickerController
- 사용자가 디바이스의 사진 라이브러리에서 이미지를 찾아 선택
- SwiftUI에는 없는 기능
- UIViewController의 하위 클래스
UIImagePickerController 래핑하기
struct MyImagePicker: UIViewControllerRepresentable {
func makeUIViewController(context:
UIViewControllerRepresentableContext<MyImagePicker>) ->
UIImagePickerController {
let picker = UIImagePickerController()
return picker
}/*필수*/
func updateUIViewController(_ uiViewController: UIImagePickerController,
context: UIViewControllerRepresentableContext<MyImagePicker>) {
}/*필수*/
}
makeUIViewController 메서드와 updateUIViewController 메서드는 필수 구현
콘텐트 뷰 설계하기
struct ContentView: View {
@State var imagePickerVisible: Bool = false // 이미지 피커 뷰 표시 유무를 제어
@State var selectedImage: Image? = Image(systemName: "photo") // 표시될 이미지
var body: some View {
ZStack {
VStack {
selectedImage?
.resizable()
.aspectRatio(contentMode: .fit)
Button(action: {
withAnimation {
self.imagePickerVisible.toggle()
}
}) {
Text("Select an Image")
}
}.padding()
if (imagePickerVisible) {
MyImagePicker()
}
}
}
}
VStack과 MYImagePicker 뷰의 인스턴스를 ZStack에 포함
-> MYImagePicker 뷰가 VStack 위로 표시
-> 이미지 선택후 이미지 피커 뷰는 사라짐
-> 선택된 이미지가 Image 뷰에 표시
MyImagePicker 완성하기
이미지 피커 뷰에서 이미지를 선택하거나 Cancel 버튼을 클릭해도 피커가 사라지지 않음
->
- 상태 프로퍼티 바인딩
struct MyImagePicker: UIViewControllerRepresentable { @Binding var imagePickerVisible: Bool @Binding var selectedImage: Image?
- 코디네이터를 델리게이트로 동작 구현
- UINavigationControllerDelegate, UIImagePicekrControllerDelegate
프로토콜 준수 - imagePickerControllerDidCancel, didFinishPickingMediaWithInfo
델리게이트 메서드 구현(이미지 선택, 취소 버튼시 알림수신)
- UINavigationControllerDelegate, UIImagePicekrControllerDelegate
class Coordinator: NSObject, UINavigationControllerDelegate,
UIImagePickerControllerDelegate {
@Binding var imagePickerVisible: Bool
@Binding var selectedImage: Image?
init(imagePickerVisible: Binding<Bool>, selectedImage: Binding<Image?>) {
_imagePickerVisible = imagePickerVisible
_selectedImage = selectedImage
}
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info:
[UIImagePickerController.InfoKey : Any]) {
let uiImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
selectedImage = Image(uiImage: uiImage)
// 이미지 뷰가 사라지기 전에 선택된 이미지를 전달
imagePickerVisible = false
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
imagePickerVisible = false
} // Image 뷰 표시 유무 결정
}
- 상태 프로퍼티 바인딩을 통해 전달
func makeCoordinator() -> Coordinator { return Coordinator(imagePickerVisible: $imagePickerVisible, selectedImage: $selectedImage) }
- 델리게이트로 코디네이터를 할당
func makeUIViewController(context: UIViewControllerRepresentableContext<MyImagePicker>) -> UIImagePickerController { let picker = UIImagePickerController() picker.delegate = context.coordinator return picker } . . /* struct MyImagePicker_Previews: PreviewProvider { static var previews: some View { MyImagePicker() .previewDevice("iPhone 11 Pro") } } */
프리뷰 구조체를 주석 처리하여 구문 오류 제거
콘텐트 뷰 완성하기
상태 프로퍼티를 MyImagePicker 인스턴스로 전달
if (imagePickerVisible) {
MyImagePicker(imagePickerVisible: $imagePickerVisible, selectedImage: $selectedImage)
}