UIKit 프로젝트에 SwiftUI 뷰를 추가하려면 SwiftUI 뷰를 포함할 수 있는 UIKit 컨트롤러인 UIHostingController
를 사용하면 된다.
import SwiftUI
struct MySwiftUIView: View {
var body: some View {
Text("Hello, SwiftUI!")
.padding()
.font(.largeTitle)
}
}
import UIKit
import SwiftUI
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupHostingController()
}
private func setupHostingController() {
// UIHostingController를 생성하여 SwiftUI 뷰(MySwiftUIView)를 포함
let hostingController = UIHostingController(rootView: MySwiftUIView())
// UIHostingController를 현재 뷰 컨트롤러의 자식 뷰 컨트롤러로 추가
addChild(hostingController)
// UIHostingController의 뷰 프레임을 현재 뷰 컨트롤러의 뷰 프레임과 동일하게 설정
hostingController.view.frame = view.frame
// 현재 뷰 컨트롤러의 뷰에 UIHostingController의 뷰를 추가
view.addSubview(hostingController.view)
// UIHostingController가 부모 뷰 컨트롤러로 이동했음을 알림
hostingController.didMove(toParent: self)
}
}
이렇게 하면 UIKit 프로젝트에서 SwiftUI 뷰를 사용할 수 있다.
import SwiftUI
import UIKit
class SwiftUiContainerVC<SwiftUiView: View>: UIViewController {
let swiftUiView: SwiftUiView
init(swiftUiView: SwiftUiView) {
self.swiftUiView = swiftUiView
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
setupHostingController()
}
private func setupHostingController() {
let hostingController = UIHostingController(rootView: swiftUiView)
addChild(hostingController)
hostingController.view.frame = view.bounds
hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(hostingController.view)
hostingController.didMove(toParent: self)
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(type: .system)
button.setTitle("Go to SwiftUI View", for: .normal)
button.addTarget(self, action: #selector(goToSwiftUIView), for: .touchUpInside)
button.frame = CGRect(x: 100, y: 200, width: 200, height: 50)
view.addSubview(button)
}
@objc func goToSwiftUIView() {
// SwiftUI 뷰를 포함하는 SwiftUiContainerVC 인스턴스 생성
let swiftUiVC = SwiftUiContainerVC(swiftUiView: MySwiftUIView())
navigationController?.pushViewController(swiftUiVC, animated: true)
}
}
struct MySwiftUIView: View {
var body: some View {
Text("Hello, SwiftUI!")
.font(.largeTitle)
.padding()
}
// 타입 메소드 정의
static func getContainerVC() -> UIViewController {
return SwiftUiContainerVC(swiftUiView: Self())
}
}
@objc func goToSwiftUIView() {
// SwiftUI 뷰의 타입 메소드 사용, SwiftUiContainerVC 인스턴스 생성
let swiftUiVC = MySwiftUIView.getContainerVC()
navigationController?.pushViewController(swiftUiVC, animated: true)
}
각각의 뷰마다 해당 타입 메소드를 구현하는게 번거로우니, 아예 SwiftUI View를 extension 해서 해당 메소드 구현 후 사용할 수도 있다.
extension View {
static func getContainerVC() -> UIViewController {
return SwiftUiContainerVC(swiftUiView: self.init())
}
}