iOS
Swift
SwiftUI

一部の画面だけ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: UIViewRepresentableContext<BackgroundView>) -> 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