728x90
UIKit을 사용하고 있는 프로젝트에서 SwiftUI도 같이 사용하고 싶으면 어떻게 해야할까요?
기존에 SceneDelegate에서 시작 화면을 설정할 땐 아래와 같이 window.rootViewController에 시작화면으로 쓸 VC를 넣어줘 동작하게 했습니다.
// UIKit만 썻을때
guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: windowScene)
// 사용할 collectionView Layout 채택
let layout = UICollectionViewFlowLayout()
let homeViewController = HomeViewController(collectionViewLayout: layout)
// 실행시 처음 보여질 rootView 설정 navigationController로
let rootNavigationController = UINavigationController(rootViewController: homeViewController)
self.window?.rootViewController = rootNavigationController
self.window?.makeKeyAndVisible()
UIKit에서 쓰던 뷰와는 다르기 때문에 SwiftUI를 UIKit 내부에서 사용할 땐 UIHostingController를 사용해서 감싸 보내야 합니다.
// SwiftUI로 시작하는 화면
let contentView = ContentView()
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
그럼 이번엔 화면 전환을 알아보겠습니다.
SwiftUI → VC
NavigationView {
List(titles, id: \\.self) { title in
let netflixVC = HomeViewControllerRepresent()
.navigationBarHidden(true)
.edgesIgnoringSafeArea(.all)
NavigationLink(title, destination: netflixVC)
}
.navigationTitle("SwiftUI to UIKit")
}
NavigationLink에 내가 전환할 화면 VC와 Title String을 보내주면 끝입니다.
그런데 HomeViewControllerRepresent는 일반적인 VIewController가 아닙니다.
SwiftUI에서 VC로 넘어가기 위해서는 VC에 특정 작업을 더 해줘야 합니다.
// SwiftUI Preview Provider (이건 그저 프리뷰 볼려구)
struct HomeViewController_Preview: PreviewProvider {
static var previews: some View {
HomeViewControllerRepresent().edgesIgnoringSafeArea(.all)
}
}
// 이 작업
struct HomeViewControllerRepresent: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
let layout = UICollectionViewLayout()
let homeViewController = HomeViewController(collectionViewLayout: layout)
return UINavigationController(rootViewController: homeViewController)
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
typealias UIViewControllerType = UIViewController
}
UIViewControllerRepresentable을 상속받는 구조체를 만들어 SwiftUI에서도 받을 수 있는 타입으로 변형해주면 문제없이 잘 작동합니다.
VC → SwiftUI
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let isFirstSection = indexPath.section == 0
let selected = isFirstSection ? mainItem : contents[indexPath.section].contentItem[indexPath.row]
let contentDetailView = ContentDetailView(item: selected)
let hostingVC = UIHostingController(rootView: contentDetailView)
self.show(hostingVC, sender: nil)
}
만약 특정 셀을 선택하면 SwiftUI로 넘어가는 코드도 보겠습니다.
처음 말했던거 같이 SwiftUI View는 UIHostingController로 감싸주고 화면 전환을 하면됩니다!
어려울 건 없고 생각보다 간단해서 좋은 거 같습니다.
728x90