- 概要
- UIViewControllerRepresentableとUIViewRepresentable
- UIKit側の実装
- SwiftUI側の実装
- UIViewControllerRepresentableを使用して呼び出す
- まとめ
概要
UIKitで作成したUIViewControllerやUIViewをUIViewControllerRepresentableやUIViewRepresentableを使用してSwiftUI側で表示する方法をご紹介します。
環境
この記事は以下のバージョン環境のもと作成されたものです。
【Xcode】14.0.1
【iOS】16.0.2
【macOS】Monterey バージョン 12.5
UIViewControllerRepresentableとUIViewRepresentable
UIViewControllerRepresentableについてのドキュメントは以下です。
https://developer.apple.com/documentation/swiftui/uiviewcontrollerrepresentable
UIViewRepresentableについてのドキュメントは以下です。
https://developer.apple.com/documentation/swiftui/uiviewrepresentable
簡単に説明すると
- UIViewControllerRepresentableはUIViewControllerをSwiftUIで使用する時に使用
- UIViewRepresentableはUIViewをSwiftUIで使用する時に使用
となりますので適時使い分けていただければと思います。
また今回はUIViewControllerRepresentableを主にサンプルで使用して解説していきますが、基本的には同じように使用できるのでUIViewRepresentableを使用したい方は読み換えていただければ幸いです。
UIKit側の実装
まずサンプルの画面としてUIKitで以下作成します。
class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() addMyLabel() addMySecondLabel() } lazy var myLabel: UILabel = { let label:UILabel = UILabel() label.frame = CGRect(x: 0, y: 0, width: 200, height: 50) label.text = "Open VC" label.textColor = .black return label }() private func addMyLabel() { myLabel.translatesAutoresizingMaskIntoConstraints = false view.addSubview(myLabel) NSLayoutConstraint.activate([ myLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), myLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 100) ]) } lazy var mySecondLabel: UILabel = { let label:UILabel = UILabel() label.frame = CGRect(x: 0, y: 0, width: 200, height: 50) label.text = "この画面はUIViewControllerによって生成されています" label.font = .systemFont(ofSize: 14) label.textColor = .black return label }() private func addMySecondLabel() { mySecondLabel.translatesAutoresizingMaskIntoConstraints = false myLabel.addSubview(mySecondLabel) NSLayoutConstraint.activate([ mySecondLabel.topAnchor.constraint(equalTo: myLabel.bottomAnchor, constant: 10), mySecondLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), ]) } }
上記のようにStoryboardを使用せずレイアウトを設定する方法については別の記事で解説を行っていますのでそちらを参照ください。
今回はこの画面をSwiftUI側から呼び出して表示させます。
SwiftUI側の実装
今回はfullScreenCoverを使用してSwiftUI側のViewからUIKit側のViewControllerを呼び出します。
まず以下のようなViewを作成します。
struct MySwiftUIView: View { @State private var showVC = false var body: some View { VStack { Button { showVC = true } label: { Text("VCを開く") } } .fullScreenCover(isPresented: $showVC) { NavigationStack { Text("ここにVCの画面を表示させたい") .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button( action: { showVC = false }, label: { Image(systemName: "xmark") } ).tint(Color.gray) } } } } } }
UIViewControllerRepresentableを使用して呼び出す
UIViewControllerRepresentableを使用して上記で作成したMyViewControllerをSwiftUIで使用できるように変換していきます。
struct MyViewControllerRepresentable : UIViewControllerRepresentable { func makeUIViewController(context: Context) -> MyViewController { return MyViewController() } //SwiftUI → UIkit func updateUIViewController(_ uiViewController: MyViewController, context: Context) { } //UIKit → SwiftUI func makeCoordinator() -> Coordinator { Coordinator() } class Coordinator { } }
SwiftUI側で呼び出す事ができます。
Text("ここにVCの画面を表示させたい")
の部分をMyViewControllerRepresentable()
に置き換えます。
今回は使用しませんでしたが、updateUIViewControllerではSwiftUIからの更新でViewControllerの状態を更新し、makeCoordinatorではViewControllerからSwiftUIに変更を伝えるために使用します。
以下それぞれドキュメントのリンク貼っておくので興味のある方は参照ください。
updateUIViewController:https://developer.apple.com/documentation/swiftui/uiviewcontrollerrepresentable/updateuiviewcontroller(_:context:)
makeCoordinator:https://developer.apple.com/documentation/swiftui/uiviewcontrollerrepresentable/makecoordinator()-32trb
まとめ
以上UIKitで作成したUIViewControllerやUIViewをUIViewControllerRepresentableやUIViewRepresentableを使用してSwiftUI側で表示する方法でした。