본문 바로가기
Swift 개발 이야기

SwiftUI 로 ImagePicker 호출하기

by 방화동한량 2020. 11. 20.
728x90

굿데이 여러분쓰 오늘은 오랜만에 스위프트유아이를 알아보도록 할게영

 

슬금슬금 좀 공부해놔야할것같은 느낌적인 너낌때문에 ;

 

UIImagePicker 를 스유에서 사용하는 방법을? Arabobsida

 

일단 SwiftUIView 로 파일을 생성해줍시다 저는 SUImagePicker 로 만들거에용

 

 

자 이렇게 되면 기본적으로 만들어지는게 아래처럼 나오게 됩니당

 

import SwiftUI

struct SUImagePicker: View {
    var body: some View {
        Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
    }
}

struct SUImagePicker_Previews: PreviewProvider {
    static var previews: some View {
        SUImagePicker()
    }
}

 

근데 ㅅㅏ실 저희는 진짜 ㄹㅇ SwiftUI 로 만들것도 아니구, 이미지피커는 사실 프리뷰가 필요 없잖아여?

 

프리뷰도 날려주고 View 도 변경해서 아래처럼 수정을 해주십당

 

struct SUImagePicker: UIViewControllerRepresentable {
    
    typealias UIViewControllerType = UIImagePickerController
    
    func makeUIViewController(context: Context) -> UIImagePickerController {
        
        let picker = UIImagePickerController()
        
        return picker
        
    }
    
    func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
        // 사용 안할거임 그냥 넣어만 두세여
    }

}

UIViewControllerRepresentable 을 채택하게 되면 먼저 어떤 종류의 뷰컨트롤러를 쓸것인가에 대해 typealias 로 결정을 해주구여 그 후에 makeUIViewController 와 updateUIViewController 함수가 자동으로? 붙게 됩니다

 

자 이제부터 할거에여

 

UIKit 시절에 저희가 이미지피커를 다루게 되면 가장 먼저 하는 일이 바로 델리게이트 설정하는 것이었죠? UINavigationControllerDelegate, UIImagePickerControllerDelegate 이 두개인데 이걸 어떻게 선언해야 ㅎㅏㄹ 것인가?

고민했다면 당신은 찐 iOS 개발자가 맞습니다 바로 Coordinator 를 사용하면 이것을 선언할 수 있습니다

다만 여기선 Coordinator 는 NSObject 도 같이 상속을 받아야합니당 이름은 꼭 Coordinator 로 하셔야되여

 

해당 Coordinator 내에서 기존에 구현하던 delegate 를 각각 구현해줍시다.

 


struct SUImagePicker: UIViewControllerRepresentable {
    
    typealias UIViewControllerType = UIImagePickerController
    
    @Environment(\.presentationMode)
    private var presentationMode // 해당 뷰컨트롤러의 노출 여부
    let sourceType: UIImagePickerController.SourceType
    let imagePicked: (UIImage) -> () // 이미지가 선택됐을때 결과 호출
    

    
    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
        
        let parent: SUImagePicker
        
        init(parent: SUImagePicker) {
            self.parent = parent
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            
            if let image = info[.originalImage] as? UIImage {
                parent.imagePicked(image)
                parent.presentationMode.wrappedValue.dismiss()
            }
            
        }
        
        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            parent.presentationMode.wrappedValue.dismiss()
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }
    
    
    func makeUIViewController(context: Context) -> UIImagePickerController {
        
        let picker = UIImagePickerController()
        
        picker.delegate = context.coordinator
        
        return picker
        
    }
    
    func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
        
    }

}


 

이미지피커의 전체 코드입니다

 

여기서 처음 ㅂㅗ는 게 @Enviroment 라는 부분일텐데여 해당 뷰의 환경변수를 선언해주는 부분으로 보시면 될듯 합니다

 

나중에 이것은 한번에 정리를 해보도록 할게용

 

자 이제 이미지피커는 다 만들었으니 이걸 실제로 ㅅㅏ용을 해봐야겠죠?

 

ContentView 에서 간단하게 작성해봅시당

 

struct ContentView: View {
    
    @State private var showingImagePicker = false
    @State var pickedImage: Image?
    
    var body: some View {
        
        VStack {
            Button(action: {
                self.showingImagePicker.toggle()
            }, label: {
                Text("Image Picker")
            }).sheet(isPresented: $showingImagePicker) {
                SUImagePicker(sourceType: .photoLibrary) { (image) in
                    
                    self.pickedImage = Image(uiImage: image)
                    print(image)
                }
            }
            pickedImage?.resizable()
                .frame(height:300)
        }


        
    }
}

 

여기서 @State 는 해당 ㅂㅕㄴ수가 변경되는것을 관찰하는 친구입니다 RxSwift 랑 비슷하쥬?

 

이제 Button 을 클릭 했을 때 이 showingImagePicker 의 상태를 변환해주고, 이 State 가 True 로 변경이 되면

 

SUImagePicker 를 sheet 를 통해 띄워줍니다.

 

그리고 Coordinator 내부에서 didFinished~ 가 호출되면 image 를 리턴해주는 클로저를 작성해놨죠? 

 

리턴된 image 를 pickedImage 에 넣어주면 요렇게 아래처럼 나오게 됨미다 참 쉽죠?

 

 

 

여기까지 아주 간단하게 UIKit 에서 사용되는 UIImagePickerController 를 스유로 사용해보았읍니다

 

그럼 다음시간에 또 만나요 안녕~~~~~