UIKit의 view controller인 UIImagePickerController를 사용함으로써 SwiftUI에서 사진을 선택할 수 있는 기능을 구현할 수 있다
# 🥨 UIView와 UIViewController
- UIView : An object that manages the content for a rectangular area on the screen.
UiView는 공식문서에서 말하는 것처럼 화면의 사각형 영역에 대한 내용을 관리하는 객체이다. 우리가 사용하는 UILabel, UIButton, UITextField 등 UI컴포넌트 들의 부모클래스가 UIView인 것이다.
https://developer.apple.com/documentation/uikit/uiview
UIView | Apple Developer Documentation
An object that manages the content for a rectangular area on the screen.
developer.apple.com
- UIViewController : An object that manages a view hierarchy for your UIKit app.
UIViewController는 UIKit 앱의 뷰 계층 구조를 관리하는 객체이며, 사용자가 보고 있는 뷰에 대한 관리 기능을 제공한다. 실제로 XCode에서 UIKit를 기반으로 하는 앱을 하나 만들면 ViewController 이름을 가진 클래스가 기본적으로 하나 있고, UIViewController를 서브클래싱하고 있다.
https://developer.apple.com/documentation/uikit/uiviewcontroller
UIViewController | Apple Developer Documentation
An object that manages a view hierarchy for your UIKit app.
developer.apple.com
# 🥨 UIViewRepresentable와 UIViewControllerRepresentable
즉, 우리는 SwiftUI에서 UIView를 쓰고 싶은 경우, UIViewController를 쓰고 싶은 경우 에 채택해야 하는 프로토콜이 다른데 각각 UIViewRepresentable와 UIViewControllerRepresentable이다. 이 글에서는 사진 선택 기능을 구현해주기 위해 UIViewControllerRepresentable를 사용해볼 것이고, UIViewRepresentable에 대해 궁금하다면 이전에 작성했던 아래 두 가지 글이 도움될 것이다.
SwiftUI에서 UIKit 사용하기 UIViewRepresentable (1) | TextField에서 clear button 사용하고 싶다면
SwiftUI에서 UIKit 사용하기 UIViewRepresentable(2) | @Binding 이란? Coordinator 란?
# 🥨 UIImagePickerController란?
UIImagePickerController는 사진 촬영, 동영상 녹화 및 사용자 미디어 라이브러리에서 항목 선택을 위한 시스템 인터페이스를 관리하는 뷰 컨트롤러이며 이 view controller를 사용해서 SwiftUI에서 사진 선택하는 기능을 구현할 것이다.
단, UIImagePickerController로는 여러개의 영상/사진을 컨트롤할 수 없고, 한번에 하나의 영상 혹은 사진을 선택할 수 있다. 여러개를 컨트롤할 수 있는 방법으로는 서드파티 API를 사용해야한다. 그렇기 때문에 이번에는 UIViewControllerRepresentable와 UIImagePickerController를 사용해서 fullScreen 혹은 sheet로 갤러리를 띄워서 내 디바이스에 있는 하나의 사진 혹은 영상을 선택하는 방법을 알아보도록하겠다.
# 🥨 UIViewControllerRepresentable 활용한 기능 구현
- SwiftUI에서 UIKit의 view controller를 사용해 주기 위해 UIViewControllerRepresentable를 채택한 구조체를 만들어준다.
- 필수적으로 정의해주어야하는 함수인 func makeUIViewController (context:) 와 func updateUIViewController (_:context:) 를 정의한다.
- 선택한 이미지의 정보를 바인딩하기 위해 Coordinator 클래스 선언. Coordinator는 UIImagePickerControllerDelegate의 역할을한다.
- SwiftUI뷰에서 선택한 이미지를 받기 위해 변수(selectedImage) 생성
- 이미지 선택에 따라 fullScreenCover 혹은 sheet 를 닫아주기 위해 관련 변수(showImagePicker) 생성
struct ImagePickerPractice : UIViewControllerRepresentable {
@Binding var image: UIImage?
@Binding var showScreen: Bool
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePickerPractice>) -> UIImagePickerController {
let viewContoller = UIImagePickerController()
viewContoller.allowsEditing = false
viewContoller.delegate = context.coordinator
return viewContoller
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePickerPractice>) {
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var parent: ImagePickerPractice
init(_ parent: ImagePickerPractice) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
parent.image = image
parent.showScreen = false
}
}
}
}
- 실제로 뷰에 적용
struct UIViewControllerRepresentablePracticeView: View {
@State private var showImagePicker : Bool = false
@State private var selectedImage : UIImage?
var body: some View {
VStack{
Button{
self.showImagePicker = true
} label : {
Text("Open Image Picker")
.padding()
.background(.green)
.cornerRadius(10)
}
Button {
print("selectedImage :", selectedImage)
} label : {
Text("Selected Image")
.padding()
.background(.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
// .fullScreenCover(isPresented: $showImagePicker){
// ImagePickerPractice(image: $selectedImage, showScreen: $showImagePicker)
// }
.sheet(isPresented: $showImagePicker){
ImagePickerPractice(image: $selectedImage, showScreen: $showImagePicker)
}
}
}
'SwiftUI' 카테고리의 다른 글
[SwiftUI] 연속한 뷰에 대해 드래그 제스처로 on/off할 수 있는 기능 구현 | 드래그 제스처 .gesture DragGesture (0) | 2023.07.13 |
---|---|
[SwiftUI] @StateObject 와 @ObservedObject (0) | 2023.06.21 |
[SwiftUI] Custom Picker로 textField 입력값 받기 (0) | 2023.06.12 |
SwiftUI에서 UIKit 사용하기 UIViewRepresentable(2) | @Binding 이란? Coordinator 란? (0) | 2023.06.09 |
SwiftUI에서 UIKit 사용하기 UIViewRepresentable (1) | TextField에서 clear button 사용하고 싶다면 (0) | 2023.06.08 |