LoginSignup
0
2

More than 1 year has passed since last update.

UIKitで作ったアプリでSwiftUIを使う

Last updated at Posted at 2022-09-05

最近Swiftでアプリを開発しています。
UIKit(Storyboard)のスタイリングがとにかく苦痛で、途中まではコードベースでなんとか頑張っていましたが限界を迎えました。

UIKitの中でもSwiftUIを使うのは少し調べると対応できたのですが、データのバインディング周りで少し苦労したので共有します。

ボトムナビに以下のような戻る・進むアイコンを表示するものを作ります。

IMG_8480.jpg

UIKitの中でSwiftUIを使う

SwiftUIのViewを作成

これだけでOK。UIKitに比べかなり分かりやすいですね。
@ObservedObjectはこのコンポーネント外の状態管理に使っています。

BottomNav.swift
import SwiftUI
import Combine

struct BottomNav: View {
    @ObservedObject var historyViewModel: HistoryViewModel
    var back: () -> Void
    var forward: () -> Void
    
    var body: some View {
        HStack(spacing: 50) {
            Button(action: { back() }
            ) {
                Image(systemName: "arrow.uturn.backward")
            }
            .disabled(historyViewModel.isDisabledBack)
            Button(action: { forward() }
            ) {
                Image(systemName: "arrow.uturn.forward")
            }
            .disabled(historyViewModel.isDisabledForward)
        }
    }
}

ObservableObjectプロトコルを使った状態管理

HistoryViewModel.swift
import Combine

class HistoryViewModel: ObservableObject {
    @Published var parentNodeBackHistory: [SCNNode] = []
    @Published var parentNodeForwardHistory: [SCNNode] = []
    
    var isDisabledBack: Bool {
        return parentNodeBackHistory.isEmpty
    }
    
    func pushBackHistory(node: SCNNode) {
        parentNodeBackHistory.append(node)
    }
}

UIViewControllerのviewにSwiftUIを表示

XxxViewController.swift
class XxxViewController: UIViewController {
    private let historyViewModel = HistoryViewModel()

    override func viewDidLoad() {
        super.viewDidLoad()
        let vc: UIHostingController = UIHostingController(
            rootView: BottomNav(
                historyViewModel: historyViewModel,
                back: popBackHistory,
                forward: { print("forward") }
            )
        );
        view.addSubview(vc.view);

        vc.view.translatesAutoresizingMaskIntoConstraints = false
        vc.view.heightAnchor.constraint(equalToConstant: 50).isActive = true
        // 左右いっぱいに底から10pxの箇所に配置
        vc.view.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
        vc.view.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
        vc.view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -10.0).isActive = true

        ... 
        
        historyViewModel.pushBackHistory(node: node)

これでXxxViewController内からSwiftUIへデータが流れるようになりました。
逆にSwiftUIの変更をUIKitに流す場合は@Publishedアトリビュート変数の.sinkメソッドを使うと実現できます。

さいごに

今までアプリ開発はFlutterでいいのではと思っていたのですが、今回iOSの新機能使いたく、Swiftでの開発が必要になりました。

SwiftUIを使うことで開発体験がかなり向上したのと、何よりiOSの新機能を使っての開発が楽しいです!

0
2
0

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
  3. You can use dark theme
What you can do with signing up
0
2