🦁UIViewControllerRepresentable / UIImagePicker🦁
지난 시간에 공부한 UIViewRepresentable이 UIView를 SwiftUI 뷰로 통합할 수 있게 하는 프로토콜이라면,
UIViewControllerRepresentable은 UIViewController를 SwiftUI 뷰로 통합하기 위한 프로토콜이다.
뷰 컨트롤러를 생성하고, 뷰 컨트롤러를 업데이트하는 메서드를 구현해야한다.
https://developer.apple.com/documentation/swiftui/uiviewcontrollerrepresentable
UIViewControllerRepresentable | Apple Developer Documentation
A view that represents a UIKit view controller.
developer.apple.com
SwiftUI에서 UIKit 기반의 UIViewController를 SwiftUI 뷰로 사용 할 수 있게 해주는 프로토콜.
SwiftUI에서 사용 가능한 뷰로 간주되고, UIViewController를 포함하고 있기 때문에 UIKit에서 제공하는 기능을 사용할 수 있다.
간단한 활용 예시
UIViewController 서브클래스 생성
class FirstViewController: UIViewController {
var labelText: String = "Default Value"
override func viewDidLoad() {
super.viewDidLoad()
//UIViewController를 만들 때 기본적으로 빈 UIView가 함께 생성됨.
/*
override func loadView() {
super.loadView()
view = UIView()
}
*/
view.backgroundColor = .blue
let label = UILabel()
label.text = labelText
label.textColor = UIColor.white
//label을 뷰 컨트롤러의 뷰에 추가함.
view.addSubview(label)
//label이 뷰컨 전체 뷰를 채우도록
label.frame = view.frame
}
}
UIViewControllerRepresentable 채택한 구조체 생성
struct BasicUiViewControllerRepresentable: UIViewControllerRepresentable {
let labelText: String
func makeUIViewController(context: Context) -> some UIViewController {
let vc = FirstViewController()
vc.labelText = labelText
return vc
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
}
UIImagePickerController
이미지 피커를 활용하는 방법을 알아보자.
https://developer.apple.com/documentation/uikit/uiimagepickercontroller/
UIImagePickerController | Apple Developer Documentation
A view controller that manages the system interfaces for taking pictures, recording movies, and choosing items from the user’s media library.
developer.apple.com
유저의 미디어 라이프러리에서 사진,영상을 선택해서 활용할 때 사용할 수 있다.
UIImagePickerControllerRepresentable
struct UIImagePickerControllerRepresentable: UIViewControllerRepresentable {
//전달할 이미지
@Binding var image: UIImage?
//sheet를 통해 피커를 띄우는 구조에서 사진을 선택하면 sheet가 dismiss되도록 하기 위해
//showScreen 바인딩 처리
@Binding var showScreen: Bool
//context는 UIViewControllerRepresentable의 instance
func makeUIViewController(context: Context) -> UIImagePickerController {
let vc = UIImagePickerController()
//이미지 편집 기능 활성화 여부
vc.allowsEditing = false
//뷰컨의 delegate를 coordinator로 설정
vc.delegate = context.coordinator
return vc
}
//SwiftUI to UIKit
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
}
//UIKit to SwiftUI
//이미지 피커 뷰컨의 delegate가 될 Coordinator 초기화 메서드
func makeCoordinator() -> Coordinator {
return Coordinator(image: $image, showScreen: $showScreen)
}
//Coordinator 클래스
// 총 3가지 프로토콜을 채택해야 한다.
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
@Binding var image: UIImage?
@Binding var showScreen: Bool
init(image: Binding<UIImage?>, showScreen: Binding<Bool>) {
self._image = image
self._showScreen = showScreen
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let newImage = info[.originalImage] as? UIImage else { return }
image = newImage
showScreen = false
}
}
}
UIImagePickerControllerDelegate 프로토콜을 구현하는 델리게이트 메서드.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let newImage = info[.originalImage] as? UIImage else { return }
image = newImage
showScreen = false
}
이미지 피커에서 유저가 미디어(이미지/비디오)를 선택한 후 호출됨.
info는 [UIImagePickerController.InfoKey : Any] 딕셔너리 형태로 되어 있음.
guard문을 통해 딕셔너리에서 .originalImage 키에 해당하는 값, 즉 선택한 이미지를 가져옴 -> UIImage로 타입캐스팅.
바인딩 되어 있는 image에 선택한 이미지를 할당 (이미지 전달)
showScreen을 false로 설정해서 피커뷰를 닫음
View
struct UIViewControllerRepresentablePrac: View {
@State private var showScreen: Bool = false
@State private var image: UIImage?
var body: some View {
VStack {
if let image = image {
Image(uiImage: image)
.resizable()
.scaledToFit()
.frame(width: 200, height: 200)
}
Button {
showScreen.toggle()
} label: {
Text("Image Picker")
}
.sheet(isPresented: $showScreen) {
UIImagePickerControllerRepresentable(image: $image, showScreen: $showScreen)
}
}
}
}
'SwiftUI > SwiftUI(Advanced)' 카테고리의 다른 글
13. Dependency Injection vs Singleton / 의존성 주입 (0) | 2023.06.27 |
---|---|
12. Protocol 프로토콜 (0) | 2023.06.27 |
10. UIViewRepresentable / Custom TextField (0) | 2023.06.25 |
9. Custom NavigationView/Link (0) | 2023.06.25 |
8. Custom TabView / TabBar 커스텀 탭뷰/탭바 (0) | 2023.06.24 |