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

**本記事は公開済みの[ドキュメント](https://developer.apple.com/documentation/swiftui)を元に作成しています。今後仕様変更などにより記載内容と異なる場合があります。予めご了承ください。**

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

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

```swift
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("にゃーん🐈")
    }
}

```

## 画面遷移先として使う
`UIHostingController`は`UIViewController`を継承しているので、そのまま遷移先としても使えます。

```swift
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](https://developer.apple.com/documentation/swiftui/uiviewrepresentable)を継承して使います。
チュートリアルの[Creating and Combining Views](https://developer.apple.com/tutorials/swiftui/creating-and-combining-views)にも記載があります。

```swift
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](https://developer.apple.com/documentation/swiftui/uihostingcontroller)
[UIViewRepresentable - SwiftUI | Apple Developer Documentation](https://developer.apple.com/documentation/swiftui/uiviewrepresentable)
[Creating and Combining Views — SwiftUI Tutorials | Apple Developer Documentation](https://developer.apple.com/tutorials/swiftui/creating-and-combining-views)