UIViewController를 SwiftUI와 통합하기

1 분 소요

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 메서드는 필수 구현

스크린샷 2022-06-18 오후 4 59 52

콘텐트 뷰 설계하기

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 뷰에 표시

스크린샷 2022-06-18 오후 5 08 33

MyImagePicker 완성하기

이미지 피커 뷰에서 이미지를 선택하거나 Cancel 버튼을 클릭해도 피커가 사라지지 않음
->

  1. 상태 프로퍼티 바인딩
    struct MyImagePicker: UIViewControllerRepresentable {
    
     @Binding var imagePickerVisible: Bool
     @Binding var selectedImage: Image?
    
  2. 코디네이터를 델리게이트로 동작 구현
    • UINavigationControllerDelegate, UIImagePicekrControllerDelegate
      프로토콜 준수
    • imagePickerControllerDidCancel, didFinishPickingMediaWithInfo
      델리게이트 메서드 구현(이미지 선택, 취소 버튼시 알림수신)
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 뷰 표시 유무 결정
}
  1. 상태 프로퍼티 바인딩을 통해 전달
    func makeCoordinator() -> Coordinator {
     return Coordinator(imagePickerVisible: $imagePickerVisible, 
                             selectedImage: $selectedImage)
    }
    
  2. 델리게이트로 코디네이터를 할당
    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)
}

스크린샷 2022-06-18 오후 5 44 58

카테고리:

업데이트: