はじめに
この記事は Elixirアドベントカレンダーのシリーズ4の5日目の記事です
ElixirDekstopのiOSアプリを以下を参考にXCodeでプロジェクトを作るところから初めて
実際に起動するまで行います
フォルダ構成
別のネイティブアプリを作るライブラリにLiveViewNativeというものがあり、そのサンプルアプリのフォルダ構成が、 app_name/native/[ios or android pj]
となっていたのでそちらを踏襲します
mkdir native
XcodeからiOSプロジェクトを作る
Xcodeを開き、新規プロジェクトを作成していきます
アプリ名を入力して nextをクリック
作成先を先ほど作成した native
の下に指定して Createをクリック
作成したら
native/bookshelf/bookshelf
となっているので
native/ios/bookshelf
とリネームしましょう
このときXcodeからRe Saveしますか?ときかれるのでキャンセルしてください
iOSサンプルアプリからファイルをコピー
サンプルアプリをXcodeで開き、以下のファイルをコピーしていきます
サンプルアプリ側の
- ZIPFoundation -> zipファイルを操作するライブラリ
- liberlang -> クロスコンパイルしたErlang実行バイナリ
- native-lib.cpp -> liberlangを起動するスクリプト
- native-lib.hpp -> 上記のヘッダーファイル
を選択してドラッグアンドドロップでコピーします
グループかリファレンスかとターゲットをきかれるので変更はせずにFinishをクリック
次にBridge-Headerを作るかを訊かれるので Createをクリック
完了すると以下のようになります
ヘッダーファイルの修正
Header.hファイルにnative-libのヘッダーファイルを読み込む設定を追加します
#import "native-lib.hpp"
ライブラリ設定
VSCodeからCartfileのファイルを作成し、以下を追加します
github "weichsel/ZIPFoundation" ~> 0.9
iosのフォルダに移動し以下を実行します
cd native/ios
carthage update --use-xcframeworks
インストールが完了したらXcodeでアプリの設定画面のGeneral
タブを表示し、Frameworks
の項目のliberlang
とZIPFoundation
のEmbed
の項目をEmbed & Sign
にします
WebViewアプリケーションと、ブリッジの作成
TodoApp.swift
のstructの内容をコピーします
import SwiftUI
@main
struct bookshelfApp: App {
@Environment(\.scenePhase) var scenePhase
var content = ContentView()
var body: some Scene {
WindowGroup {
self.content
}
.onChange(of: scenePhase) { phase in
switch phase {
case .background:
print(".background")
case .active:
print(".active")
if let bridge = Bridge.instance {
bridge.reinit()
}
default: break
}
}
}
}
アプリ起動時にconent
を表示し、アプリがバックグラウンドになったらログを出力し、バックグラウンドからアクティブになったらPhoenixアプリケーションとのブリッジを再度作成します
もとからある ContentView.swiftを削除し、サンプルアプリから以下のファイルをドラッグアンドドロップでコピーします
- ContentView.swift -> アプリの画面でセーフエリアとWebviewを表示
- WebViewController.swift -> WebViewの初期化処理と画面更新時の処理
- WebView.swift -> 表示するWebviewの設定
- Bridge.swift -> Erlangの起動と接続処理
ビルドスクリプト作成
run_mixをVSCode経由でコピーしビルドスクリプトをPhoenix Projectに合わせて編集します
#!/bin/bash
set -e
# Setting up the PATH environment
[ -s /opt/homebrew/bin/brew ] && eval $(/opt/homebrew/bin/brew shellenv)
[ -s /usr/local/bin/brew ] && eval $(/usr/local/bin/brew shellenv)
# This loads nvm
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# This loads asdf
if [ -s "$HOMEBREW_PREFIX/opt/asdf/libexec/asdf.sh" ]; then
\. "$HOMEBREW_PREFIX/opt/asdf/libexec/asdf.sh"
elif [ -s "$HOME/.asdf/asdf.sh" ]; then
\. "$HOME/.asdf/asdf.sh"
fi
BASE=`pwd`
export MIX_ENV=prod
export MIX_TARGET=ios
mix local.hex --force --if-missing
mix local.rebar --force --if-missing
- if [ ! -d "elixir-app" ]; then
- git clone https://github.com/elixir-desktop/desktop-example-app.git elixir-app
- fi
- # using the right runtime versions
- if [ ! -f "elixir/.tool-versions" ]; then
- cp .tool-versions elixir-app/
- fi
- cd elixir-app
+ # Phoenix PJまでのパスに変更
+ cd ../../
if [ ! -d "deps/desktop" ]; then
mix deps.get
fi
# tailwindのみの場合コメントアウト
# if [ ! -d "assets/node_modules" ]; then
# cd assets && npm i && cd ..
# fi
- if [ -f "$BASE/todoapp/app.zip" ]; then
- rm "$BASE/todoapp/app.zip"
- fi
+ # xcodeで作成したプロジェクト名に変更
+ if [ -f "$BASE/bookshelf/app.zip" ]; then
+ rm "$BASE/bookshelf/app.zip"
+ fi
mix assets.deploy && \
mix release --overwrite && \
- cd _build/ios_prod/rel/todo_app && \
- zip -9r "$BASE/todoapp/app.zip" lib/ releases/ --exclude "*.so"
+ cd _build/ios_prod/rel/bookshelf && \
+ zip -9r "$BASE/bookshelf/app.zip" lib/ releases/ --exclude "*.so"
ビルド実行
ErlangとElixirのバージョンを以下のコマンドで切り替えます
asdf global erlang 25.0.4
asdf global elixir 1.15.7-otp-25
iosのフォルダに移動してrun_mix
を実行します
cd native/ios/
./run_mix
ビルドが正常に完了したら、bookshelf
フォルダにapp.zip
を追加します
ファイルを追加したらXcodeの実行ボタンをクリックすると以下のように表示されます
最後に
Xcodeでプロジェクトを作るところから実際にElixirDesktopが動くところまでを実装しました
ファイルをXcode経由でコピーしたりといろいろ面倒なので、LiveViewNativeみたいに自動化されないかなーとは思っています
次はAndroidプロジェクトを作成していきます
本記事は以上になります、ありがとうございました