이번에 솝커톤을 나가면서 경험했던 UIkit 과 SwiftUI를 둘다 사용해야 했던 상황에서 경험한 멀티모듈 사용법 정리
UIHostingController: UIKit에서 SwiftUI View를 사용하기
UIKit 기반 프로젝트에서 SwiftUI 뷰를 호스팅하는 데 사용됩니다.
- 사용 예시:
- SwiftUI로 만든 특정 뷰를 기존 UIKit 뷰 계층에 삽입할 때.
- UIKit의 UIViewController나 UINavigationController 위에 SwiftUI 뷰를 추가할 수 있습니다.
동작 방식
SwiftUI 뷰를 UIKit에서 UIHostingController의 rootView로 설정하면, UIKit에서 SwiftUI 뷰를 렌더링합니다.
import UIkit
import SwiftUI
private func pushToQuestDetailView() {
// 1. SwiftUI 뷰 생성과 동시에 클로저 전달
let questDetailView = QuestDetailView(onPhotoTaken: { [weak self] in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self?.showCustomAlert()
}
})
// 2. UIHostingController로 SwiftUI 뷰 래핑
let hostingController = UIHostingController(rootView: questDetailView)
// 3. UIKit의 네비게이션 기능 설정
hostingController.navigationItem.hidesBackButton = true
setupCustomBackButton(for: hostingController)
// 4. 네비게이션 컨트롤러를 통한 화면 전환
navigationController?.pushViewController(hostingController, animated: true)
}
특징
- UIKit 환경(HomeViewController)에서 SwiftUI 뷰(QuestDetailView)를 사용하기 위해 UIHostingController를 사용
- UIHostingController가 SwiftUI 뷰를 UIKit의 뷰 계층구조에 통합하는 "호스트" 역할 수행
- 네비게이션 컨트롤러 등 UIKit의 기능을 그대로 활용 가능
- UIKit에서 SwiftUI 전체 뷰를 가져와야 할 때 사용.
- SwiftUI 뷰는 독립적으로 렌더링되므로 UIKit의 UIView 계층 위에 SwiftUI 뷰를 덧씌우는 개념에 가깝다.
2. UIViewRepresentable: SwiftUI에서 UIKit 뷰를 사용하는 방법
- 역할: SwiftUI 기반 프로젝트에서 UIKit의 UIView나 UIViewController를 SwiftUI 뷰로 "감싸는" 데 사용됩니다.
- 사용 예시:
- UIKit에서 제공하는 특정 기능(MapKit, AVPlayerViewController 등)을 SwiftUI에서 활용하고 싶을 때.
- SwiftUI에서 아직 지원하지 않는 UIKit의 고유 뷰를 가져와야 할 때.
동작 방식
UIViewRepresentable 프로토콜을 채택한 구조체를 만들어 UIKit 뷰를 SwiftUI에서 사용할 수 있도록 래핑합니다.
// ImagePicker: UIKit의 UIImagePickerController를 SwiftUI에서 사용
struct ImagePicker: UIViewControllerRepresentable {
@Binding var image: UIImage?
var sourceType: UIImagePickerController.SourceType
var onImagePicked: (() -> Void)?
// 1. UIKit 뷰컨트롤러 생성
func makeUIViewController(context: Context) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.sourceType = sourceType
picker.delegate = context.coordinator
return picker
}
// 2. 업데이트 로직
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
// 3. Coordinator 생성
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
}
// QuestDetailView에서의 실제 사용
struct QuestDetailView: View {
@State private var showImagePicker = false
@State private var selectedImage: UIImage?
var body: some View {
// SwiftUI 뷰에서 UIKit 컴포넌트 사용
ImagePicker(image: $selectedImage, sourceType: .camera) {
// 이미지 선택 완료 시 동작
}
}
}
- SwiftUI 환경에서 UIKit의 UIImagePickerController를 사용하기 위해 UIViewRepresentable 프로토콜 채택
- makeUIViewController를 통해 실제 UIKit 컴포넌트 생성
- Coordinator를 통해 UIKit의 델리게이트 패턴을 SwiftUI에서 처리
특징
- SwiftUI에서 UIKit의 특정 뷰만 가져올 때 사용.
- UIKit의 동작을 makeUIView와 updateUIView를 통해 SwiftUI 상태에 맞게 조정.
언제 UIHostingController vs UIViewRepresentable를 사용할까?
기능 UIHostingController UIViewRepresentable
사용 방향 | UIKit → SwiftUI | SwiftUI → UIKit |
사용 목적 | SwiftUI 전체 화면 또는 View를 UIKit에 통합 | UIKit의 특정 뷰나 기능을 SwiftUI에 통합 |
유즈 케이스 | UIKit 앱에 SwiftUI를 추가하거나 섞고 싶을 때 | SwiftUI 앱에서 UIKit 뷰를 직접 써야 할 때 |
결론
- UIHostingController는 UIKit에서 SwiftUI 전체를 사용
- UIViewRepresentable은 SwiftUI에서 UIKit의 특정 기능만 가져온다.
'IOS - Swift > SwiftUI' 카테고리의 다른 글
[iOS/SwiftUI] SwiftUI에서 특정부분만 UIkit으로 추출해서 사용하기 (0) | 2024.12.03 |
---|---|
[iOS/SwiftUI] Property Wrapper - 기본편 (1) | 2024.03.29 |
[iOS/SwiftUI] LunchScreen 적용하기 (0) | 2023.12.31 |