ElixirDesktop iOSを動かす

# はじめに

本記事はElixirDesktopiOS Exampleを以下の記事で実際にやってみた備忘録になります

https://qiita.com/RyoWakabayashi/items/f5d97a7e857983eac7a4

https://github.com/elixir-desktop/ios-example-app

# 環境
CPU M1
OS masOS  Monterey 12.4
XCode 13.4.1
elixir asdf elixir 1.13.0-otp-25
elrang asdf erlang 25.0.3

# 下準備

asdfは無効化するのでhomebrewのelixir
erlangのバージョンマネージャー　kerl
swiftのパッケージマネージャーの carthage
asdfをディレクトリ毎に無効化設定をする direnv
をそれぞれインストールします

```bash
brew install elixir kerl carthage direnv
```

ElixirDesktop用にカスタムしたerlangをインストールします
ビルドスクリプトで ~/projects/を参照するのでこの通りにしておきましょう

```
mkdir -p ~/projects/
kerl build git https://github.com/diodechain/otp.git diode/beta 24.beta
kerl install 24.beta ~/projects/24.beta
```

# プロジェクトセットアップ

cloneしてきます
```
git clone https://github.com/elixir-desktop/ios-example-app.git
```

プロジェクトに移動してライブラリのインストールを行います

```
cd ios-example-app &&　carthage update --use-xcframeworks
```

asdfだとうまくビルドができないため無効化してシステムのElixirを使うようにします

```
touch .envrc
```
userは適宜自分のユーザー名に変えてください

```.envrc
PATH_rm /Users/user/.asdf/shims
PATH_rm /Users/user/.asdf/bin
```
設定を書いたら有効化します
```
direnv allow
```
これでasdfが無効化されました

完了したらプロジェクトをXCodeで開きます

```
open todoapp.xcodeproj
```

# ビルド開始

とりあえず実行します
まぁ失敗するので色々直していきます

## プロジェクトの設定

Gneral tabでbundle identifierを適当に変えます今回は`exmaple3`としてます

![スクリーンショット 2022-07-28 23.19.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/1b1b47c0-d9c2-120f-230e-69ec1bc27132.png)

各種ライブラリが埋め込まれていないので Embed & Sign に変更します

![スクリーンショット 2022-07-28 23.20.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/07197b18-16a5-432f-0c29-e65cbf5e3b9f.png)

Signning & Capabilities tabのteamを自分のものに変更します

![スクリーンショット 2022-07-28 23.21.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/7fef0655-cecb-55c9-f374-bef5d7d8a59a.png)

Build Settings tabで 表示をbasicからallに変更して Enable Bitcodeをnoにします

![スクリーンショット 2022-07-28 23.24.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/fab3d7bd-a43d-a8c6-4932-bd42e0ba7d28.png)

うまくOSを判別してくれないようなので、環境変数のセットします

![スクリーンショット 2022-07-28 23.36.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/d769357a-3cc7-7130-3a1c-685c93053e33.png)

edit schemeでArgumentsタブを選択肢環境変数に ELIXIR_DESKTOP_OS に ios をセットします

![スクリーンショット 2022-07-28 23.37.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/714bb62d-5ad5-c407-fb0e-872a39e881c8.png)


## Elixirのライブラリアップデート

Elixirのコードがelixir-appという名前でgit cloneされているのでそちらに移動します

```
cd elixir-app
```

wxとdart-sassを最新にします

```elixir-app/mix.exs
defmodule Todo.MixProject do
  use Mix.Project

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      {:ecto_sqlite3, "~> 0.7"},
      # {:desktop, path: "../desktop"},
      {:desktop, github: "elixir-desktop/desktop", tag: "v1.4.0"},
      {:wx, "~> 1.0.10", hex: :bridge, targets: [:android, :ios]}, # 追加
      # Phoenix
      {:phoenix, "~> 1.6"},
      {:phoenix_live_view, "~> 0.16"},
      {:phoenix_html, "~> 3.0"},
      {:phoenix_live_reload, "~> 1.3", only: [:dev]},
      {:gettext, "~> 0.18"},
      {:plug_cowboy, "~> 2.5"},
      {:jason, "~> 1.2"},

      # Assets
      {:esbuild, "~> 0.2", runtime: Mix.env() == :dev},
      {:dart_sass, "~> 0.5", runtime: Mix.env() == :dev}, # 0.5に変更

      # Credo
      {:credo, "~> 1.5", only: [:dev, :test], runtime: false}
    ]
  end
end
```

リンクが切れていないsassのバージョンを設定します
```elixir-app/config/config.exs
config :dart_sass,
  version: "1.49.11", # 1.49.11に上げる
  default: [
    args: ~w(css/app.scss ../priv/static/assets/app.css),
    cd: Path.expand("../assets", __DIR__)
  ]
```
完了したら mix deps.getを行い上に戻ります

```
mix deps.get
cd ..
```

再度ビルドを行い・・・

無事動きました！

![89c748bf746d39335ee0c7c7b55ed986.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64198/5c20f53b-d523-f033-e10d-840767781143.gif)


# 実機でエラー
実機で実行しようとするとsqliteのファイルが作成されずエラーになったので原因を探ったところ
swift側でアプリのhomeの場所は以下にセットされているのですが
```
/var/mobile/Containers/Data/Application/48C9C67D-400B-466B-B1C6-44695A00771F/Library/io.elixirdesktop.example
```
実際にファイルを作ろうとしたのは
```
/private/var/mobile/Containers/Data/Application/48C9C67D-400B-466B-B1C6-44695A00771F/.config/todo
```

とずれていたのが原因でした

対応するにはbundle identifierが固定値になっているので関数で取得するようにします

```todoapp/Bridge.swift
// line 41
home = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask)[0].appendingPathComponent(Bundle.main.bundleIdentifier!)
```

それでも解決しなかったのでElixir側でパスを指定します
xcodeで指定したidentifilerとLibraryを追加します
ですがこれだとシミュレーターで動かないのでもとの方は残しておきましょう
環境変数とかで分けれるといいですね


```elixir-app/lib/todo_app.ex
  def config_dir() do
    # Path.join([Desktop.OS.home(), ".config", "todo"])
    Path.join([Desktop.OS.home(), "Library", "io.elixirdesktop.example3", ".config", "todo"])
  end
```
これで再度ビルドを実行して無事実機でも動きました！

# 最後に
これでAndroidとiOS両方のサンプルが動くようになりました
あとはDB周りがまだ使い勝手が良くないので色々検証してみたいと思います
本記事は以上になりますありがとうございました

# 参考
https://qiita.com/RyoWakabayashi/items/f5d97a7e857983eac7a4
https://github.com/elixir-desktop/ios-example-app
https://typememo.jp/tech/chromium-build-macos-should-be-disable-asdf/