감자주먹밥

UIKit with SwiftUI 화면전환 본문

IOS/UIKit

UIKit with SwiftUI 화면전환

JustHm 2022. 12. 8. 01:14
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
Comments