search
LoginSignup
101

More than 3 years have passed since last update.

posted at

updated at

Organization

一部の画面だけSwiftUIを使いたいとき

本記事は公開済みのドキュメントを元に作成しています。今後仕様変更などにより記載内容と異なる場合があります。予めご了承ください。

はじめに

SwiftUIを触っていて、
「SwiftUIのViewとUIKitのUIView間の連携ってどうやるんだ?」となったので調べました。
結論から言うと、UIHostingController/UIViewRepresentableでなんとかなりそうです。

UIViewの中で画面の一部として使う

UIView/UIViewControllerの中でSwiftUIのViewを使う場合は、UIHostingControllerでラップしてあげる形になります。
こんな感じで。

import SwiftUI

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let vc: UIHostingController = UIHostingController(rootView: SubView())
        self.addChild(vc)
        self.view.addSubview(vc.view)
        vc.didMove(toParent: self)

        vc.view.translatesAutoresizingMaskIntoConstraints = false
        vc.view.heightAnchor.constraint(equalToConstant: 320).isActive = true
        vc.view.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 16).isActive = true
        vc.view.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -16).isActive = true
        vc.view.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    }
}

struct SubView : View {
    var body: some View {
        Text("にゃーん🐈")
    }
}

画面遷移先として使う

UIHostingControllerUIViewControllerを継承しているので、そのまま遷移先としても使えます。

import SwiftUI

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let button: UIButton = UIButton(type: .system)
        button.setTitle("🐈", for: .normal)
        button.addTarget(self, action: #selector(didTapTransitButton(_:)), for: .touchUpInside)
        self.view.addSubview(button)

        button.translatesAutoresizingMaskIntoConstraints = false
        button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
        button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
    }

    @objc func didTapTransitButton(_ sender: UIButton) {
        self.present(UIHostingController(rootView: DetailView()), animated: true)
    }
}

struct DetailView : View {
    var body: some View {
        Text("にゃーん🐈")
    }
}

Viewの中でUIViewを使う

逆にViewの中でUIViewを使いたい時は、UIViewRepresentableを継承して使います。
チュートリアルのCreating and Combining Viewsにも記載があります。

import SwiftUI

struct ContentView: View {
    var body: some View {
        ZStack {
            BackgroundView()
            Text("にゃーん🐈")
        }
    }
}

struct BackgroundView: UIViewRepresentable {
    func makeUIView(context: Context) -> UIView {
        let view: UIView = UIView()
        view.backgroundColor = UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1.0)
        return view
    }

    func updateUIView(_ uiView: UIView, context: Context) {
        //
    }
}

参考

UIHostingController - SwiftUI | Apple Developer Documentation
UIViewRepresentable - SwiftUI | Apple Developer Documentation
Creating and Combining Views — SwiftUI Tutorials | Apple Developer Documentation

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
101