SwiftUI+Go+Heroku Postgresで遊んでみた感想と知見
はじめに
あけましておめでとうございます。今年もよろしくお願いいたします。
本年度一発目の記事は、技術のインプットアウトプット通じての備忘録シリーズです。
作ったもの
今回サンプルとしてつくったものは単語帳アプリです。 ざっと機能としては
- ユーザーが設定したカテゴリを選択
- 選択後カテゴリに該当する単語が出現、答えを任意のタイミングで見ることができる
のシンプルな感じで 1 日で開発が終わるようなレベルに設定しました。ちなみにユーザーは自分しかいない前提で進めています
採用技術
技術は以下の通りです。採用理由は自分が使いたかったから!!(結局興味があったりモチベが出るものが一番いいのよ個人開発は)
- Client (app): SwiftUI+Combine
- Server: Go(フレームワーク: gin)
- DB: Heroku Postgres
バックエンド側は Heroku フル活用で事足りるはずなので使わせてもらって、アプリ側は久々 SwiftUI で書きました
得た知見(ハマったところ多め)
Client, Server, DB, Heroku 周りで詰まったところをまとめます。これは余談ですが、Go で作ったアプリケーションを Heroku で扱う公式チュートリアルが優秀すぎて、想像以上にスムーズにできたのでよかったです
SwiftUI で元の画面に戻る処理
UIKit でいうdismiss(animated:)
を SwiftUI でやるにはPresentationMode
構造体にアクセスして、dismiss()
を呼んであげます
// 遷移元のView
// presentationModeの環境変数を取得
@Environment(\.presentationMode) var presentationMode
// 元画面に戻る処理
presentationMode.wrappedValue.dismiss()
iOS15 以降なら、環境変数presentationMode
でなくdismiss
にアクセスすればすんなりできそうです(参考)
NavigationLink で遷移した画面の上に謎のスペースができる際の対処法
UI を調整している時に、なぜか上側に謎のスペースができていたのでnavigationBarTitleDisplayMode
を.inline
に指定して解決(参考)
HogeView {
// SwiftUI.View
}
.navigationBarTitleDisplayMode(.inline)
特定の処理が終わったタイミングで NavigationLink を使って画面遷移したい
API との通信処理が終わったあとに画面遷移をしたいときは、NavigationLink
のisActive
フラグを通信が終わった時にtrue
に変えてあげることで実現できます。(参考)
NavigationLink(destination: QuizView(words: viewModel.words), isActive: $shouldShowQuizView) {
Button(action: {
viewModel.fetchWords(
by: selectedCategoryId,
success: {
// success callbackのときにshouldShowQuizViewをtrueにする
self.shouldShowQuizView = true
},
failure: {
print("Failed to fetch data from api")
}
)
}) {
Text("START")
}
}
Heroku デプロイでapp not compatible with buildpack
(Go 編)
以下コマンドで Go のバージョンとモジュールの依存関係を記したgo.mod
を作成し、デプロイしてあげて解決。(参考)
go mod init {GIT_REPOSITORY_URL}
Heroku デプロイで cannot execute binary file: Exec format error
ローカルでコンパイルの際に OS とアーキテクチャ の指定をしてあげてクロスコンパイル、その後バイナリをデプロイすることで解決(参考 1, 2)
## fish
env GOOS=linux GOARCH=amd64 go build -o bin/terminology-memo-api -v .
Heroku デプロイでapp[web.1]: bash: bin/: No such file or directory
Procfile
でバイナリの存在するパスを記して解決
web: bin/{BINARY_NAME}
参考: 上述の公式チュートリアル
Go で作ったアプリケーションでno required module provides package
下記コマンドを実行して依存しているモジュールを更新(参考)
go mod tidy
改行コードを PostgreSQL で扱う
E を追加したい文字列の先頭にいれてあげて解決(参考)
INSERT INTO words (name) VALUES (E'明日\n晴れるかな')
updated_at
を自動的に更新してくれる制約を追加
MySQL ならon update current_timestamp
を DDL に追加してあげるだけで OK だが、PostgreSQL だと同等の機能がないので、トリガーを描いてあげる必要がある。。。ので、このサイトを参考に書かせていただきました
最後に
やる気が出た時にガツッとやる開発は久々だったが、楽しいしまた違う学びがある。