wootan's diary

iOSアプリ開発を中心としたエンジニアブログ

Reluxアプリ開発の舞台裏 便利な開発用機能

この記事は Relux Advent Calendar 2017 23日目の記事です。
今回は開発の舞台裏ということで、普段はユーザーの目に触れることのない開発用機能などをご紹介します。

入社時のアプリの問題

僕が宿泊予約サービス Relux を運用する Loco Partners にジョインした当初は
開発版のアプリがどのサーバに接続されているかが判別できませんでした。
本番環境と見分けがつかず、誤って本番環境のホテル・旅館を予約してしまう事故も発生していました。

改善したこと

まず、アプリがどのサーバに接続しているかわかるように、画面下端に半透明のバーを追加しました。
f:id:wootan1102:20171212160625p:plain:w300
こちらは本番環境に接続している時に表示されるバーです。

本番環境はレッド、開発環境はグレーのように環境ごとに色をわけています。
これにより色だけでどのサーバに接続されているか判断できるようになっています。
また、ジョインしたばかりの人も迷わないように右下に接続先を表示しています。
すべての画面でこのバーが表示されるようになっているので、誤って本番環境で予約してしまうということもなくなりました。


次にアプリの接続先のサーバを変更できるようにしました。
接続先のサーバは上記のバーをタップすることで切り替えられるようにしました。
タップするたびに
本番環境 → ステージング環境 → 開発環境 → ... というように接続先が変更されるようになっています。
ただし、デバッグ中に誤タップで接続先がかわってしまうということがないように
未ログイン状態でかつホーム画面でのみ切り替わるという制限を設けました。
改善前は環境ごとにアプリをビルドし、デバッグ担当者はそれを再インストールする必要があったのでかなり工数削減できたと思います。

Release版がDebug版に上書きされてしまう問題

開発版でサーバの接続先を変更できるようにしたので後回しにしていたのですが
社内で動作確認のために Release版とDebug版を入れかえている方がかなりいたので対応しました。

改善したこと

llcc.hatenablog.com
こちらの記事を参考にして Release版とDebug版を共存できるようにしました。
App Extensionsに対応している場合は、そちらもRelease版とDebug版を分ける必要があり少し大変でした。

さらにアイコンも見分けがつく用にRelease版とDebug版でわけることにしました。
上記の記事で紹介されている方法でもよかったのですが、アイコンをわざわざ用意するのが面倒だったので fastlane-plugin-badge を利用しています。

github.com

f:id:wootan1102:20171213141012j:plain:w300
アイコンはこのように表示されます。(冬仕様のトナカイさんの首が...)


Fastfileでは下記のようにしています。

add_badge(shield: "Version-#{get_version_number}-blue", no_badge: true)
...
reset_git_repo(files: icons, force: true)

add_badgeでバッジ付きのアイコンを生成し、
アプリの配信アップロードが終わったあとに git reset しています。

開発・デバッグをスピードアップするための効率化

さらに開発・デバッグの効率をよくするために
繰り返し行う操作や面倒な操作をサポートする機能を実装しました。
この中からいくつか紹介したいと思います。

f:id:wootan1102:20171213165320g:plain
端末を振るとUIAlertControllerで開発・デバッグ用のメニューが表示されます。
このメニューはどの画面からでも呼び出せるようになっています。

サーバの接続先バーを非表示にする

開発途中のスクリーンショットが必要な場合や
デザイン確認などで一時的にバーをはずしたいという要望があったので実装しました。
操作後にはずしたままにするとRelease版と間違えてしまいそうだったので
画面遷移すると表示されるようにしています。

アプリからSlackへスクリーンショットを送信する

弊社ではデバッグ用にテスト端末をレンタルしているのですが
特定のアカウントで App Store や Slack にログインしたままにするわけにはいかず、
AirdropMacスクリーンショットを転送し、MacからSlackへアップロードするという手順を踏んでいました。

何枚も送信したい場合はこれでは手間なので
アプリ上でスクリーンショットを擬似的に合成して送信することにしました。
ソースコードをみていただければわかりますが、Windowのlayerを重ねて描画しています。

 UIApplication *application = [UIApplication sharedApplication];
UIWindow *window = application.keyWindow;
UIGraphicsBeginImageContextWithOptions(window.bounds.size, NO, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
for (UIWindow *aWIndow in application.windows) {
    [aWIndow.layer renderInContext:context];
}
UIImage *captureImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return captureImage;

ここで生成したUIImageをSlackに送信しています。

f:id:wootan1102:20171213171209p:plain

Slackではこのように表示されます。
不具合の報告などにも使われるので
ユーザID、言語、接続先サーバなども送信するようにしています。

FirebaseデバイストークンをSlackへ送信する

Relux では Push Notification に Firebase を採用しています。
FirebaseデバイストークンはDBで保存しているのでSELECTすれば良いのですが
こちらもSlackに送信するようにしました。
アプリを再インストールするとデバイストークンが変更されるので地味に便利です。

Firebase Remote Config の設定値を表示する

Firebase Remote Config は便利なのですが現在設定されている値がわからず困ることがありました。
そこで Key, Value を表示する一覧を実装しました。また、値をすぐ反映するためのフェッチ機能も実装しています。

f:id:wootan1102:20171222195507p:plain
ほとんど中身はお見せできないのですがこのように表示されます。

初回起動時の挙動を確認するためにローカルデータをすべて削除する

初回起動時の挙動を確認するためにアプリを一度アンインストールしてからインストールする必要がありました。
それではあまりにも効率が悪すぎるのでローカルデータをすべて削除する機能を追加しました。
こちらもかなり工数が削減できたと思います。

最後に

いかがでしたか?
紹介した機能以外にも画像のキャッシュクリアなどの基本的なものから
ちょっとマニアックなデバッグ用機能もあります。
どれも最初は自分が楽をするためにおこなっていた改善ですが
いつの間にかチームのためにもなっていました。これからもそんな改善を繰り返していきたいと思います!

そしてアプリを一緒につくってくれる仲間を募集中です。
興味がある方はお話だけでも聞きにきてください!
www.wantedly.com