Xcodeを使わずUIKitのレイアウトをjsonで書いて複数の実機で同時にHotReloadするライブラリを作った

#概要

タイトルの通りです。
SwiftUIが話題になってきている令和の時代にUIKitに焦点を当てたライブラリを作ってみました。
名前は__UIKitHotReload__です。
[Githubはこちら。](https://github.com/sakiyamaK/UIKitHotReload)



## 概要

- レイアウトを__jsonで記述__します
- __複数の実機で同時に__HotReloadさせることができます
- 既存のUIKitのレイアウトと組み合わせ可能です
- Firestoreのsnapshotの機能を使います
- Releaseビルド時はbundleされたjsonファイルを利用するのでHotReloadしません
- xibやstoryboardを置き換えるものなのでViewControllerは必要です
- ボタンタップ時のアクションなどもswiftで記載する必要があります

# 動き
こんな感じで複数のシミュレータで同時にHotReloadできます。
<img src="https://i.gyazo.com/2b644cce3fe572ec57bddd47d4a06d80.gif" />

より詳細な動画はYouTubeにあげています。
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/Pb-ooDfKP9A/0.jpg)](http://www.youtube.com/watch?v=Pb-ooDfKP9A)

# レイアウトの組み方

以下のような画面の中央に赤丸のviewを表示させるシンプルな画面の例を記します。

<img src="https://i.gyazo.com/dff8b2f5cbe71b7e6f52659c39963361.png" width=200 />

## ViewController.swift

`ViewController`から読み込みたいViewの`json`を指定します。

```swift:ViewController.swift
import UIKit
import UIKitHotReload

final class ViewsViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()
    // views/sample.jsonを読み込む場合
    self.view.loadHotReload(dirName: "views", jsonFileName: "sample") { result in
      switch result {
      case .failure(let error):
        //読み込み失敗
        print(error.localizedDescription)
      default:
        //読み込み成功
        break
      }
    }
  }
}
```

## views/sample.json

基本的にUIKitのクラス名やパラメータ名と連動したkeyでjsonを記述します。

```json:views/sample.json
{
  "class": "view",
  "background_color": [
    1,
    1,
    1
  ],
  "subviews": [
    {
      "class": "view",
      "background_color": [
        1,
        0,
        0
      ],
      "circle": {
        "rad": 50
      },
      "layout": {
        "center": {
          "x": {
            "v": 0
          },
          "y": {
            "v": 0
          }
        },
        "size": {
          "width": {
            "v": 100
          },
          "height": {
            "v": 100
          }
        }
      }
    }
  ]
}
```


# HotReloadする仕組み

<img src="https://i.gyazo.com/776f3a1921fc7bafc8da76a949b17e9c.png" width=800 />

UIKitHotReloadはjsonからUIKitのViewを構築していくトランスパイラとして機能しています。
VSCodeの`Run On Script`のアドオンなどでjsonを保存したらfirestoreにアップロードさせます。
firestoreのリアルタイムにローカル(スマホアプリ)とサーバーのデータを同期する機能により、即時にアプリ内の画面がリロードさせjsonからUIKitのレイアウトを再構築します。
__リリースビルドの場合はbundleされたjsonを読み込むためfirestoreと連携はしません。__


# SwiftUIと比べて

## メリット
・iOS13以前でも動く
・既存のUIKitのソースコードと親和性が高い
・一度インストールしたらXcodeすら立ち上げる必要がないので中古のmacbook airでもレイアウトが組める
・複数の実機で同時にHotReloadでレイアウトを確認できるので、一度チームメンバーに配布したら、再配信することなく全員の意見を即時反映させることができる

## デメリット
・firestoreの機能が前提
・VSCodeの`Run On Script`(保存したらスクリプト実行)が前提
・初期設定に手間がかかる
・オンライン環境でないとHotReloadは機能しない
・jsonで補完が効かない
・サポートしているviewの種類が少ない


# サポートしているView

UIView
UIButton
UILabel
UIImageView
UITextField
UIScrollView
UIStackView
UITableView
UITableViewCell

# その他の例

## UIView

UIViewのパラメータを使った実装例です

[ViewsViewController.swift](
https://github.com/sakiyamaK/UIKitHotReload/blob/main/Example/UIKitHotReload/ViewController/ViewsViewController.swift)
[views.json](https://github.com/sakiyamaK/UIKitHotReload/blob/main/Example/UIKitHotReload/views/views.json)

<img src="https://i.gyazo.com/3adb1c2bfccc52693c50eef3b7ec7ded.png" width=200 />

## UIButton

UIButtonを使った実装例です
jsonからswiftの連携をしたボタンタップ時の処理も記述しています

[ButtonsViewController.swift](
https://github.com/sakiyamaK/UIKitHotReload/blob/main/Example/UIKitHotReload/ViewController/ButtonsViewController.swift)
[buttons.json](https://github.com/sakiyamaK/UIKitHotReload/blob/main/Example/UIKitHotReload/views/buttons.json)

<img src="https://i.gyazo.com/0b38c2cfdcfd0d5428326a2cc1488285.png" width=200 />

## Twitter風
UITableViewの例としてTwitter風のセルを表示させています。

[TwitterTimelineViewController.swift](
https://github.com/sakiyamaK/UIKitHotReload/blob/main/Example/UIKitHotReload/ViewController/Twitter/TwitterTimelineViewController.swift)
[twitter_timeline.json](https://github.com/sakiyamaK/UIKitHotReload/blob/main/Example/UIKitHotReload/views/twitter_timeline.json)
[twitter_timeline_cell.json](https://github.com/sakiyamaK/UIKitHotReload/blob/main/Example/UIKitHotReload/components/twitter_timeline_cell.json)

<img src="https://i.gyazo.com/e95908e709985f188da8e66a8706f29b.png" width=200 />

# 今後
初期設定をシンプルにする
サポートするviewの追加
複数人が同時編集できるようにする
テストコードを入れる

# 終わり
CocoaPodsの登録も初めてでしたが意外と簡単にできるんだなと思いました。
オープンソースのライブラリの作法なんかもよく分かってもらず、ご意見などいただけると嬉しいです。