Relux iOSアプリ開発にfastlaneを導入してテストアプリ配信を自動化
ポケモンGOが盛り上がっていますね!
ようやく60種類あつめました。コンプリートにはまだまだかかりそうです...
本エントリでは fastlane の導入について書きたいと思います。
fastlaneを導入することでテストアプリの配信コスト、AppStoreの申請コストを
大幅に削減することができました。ぜひ参考にしてみてください。
レールの概念
fastlaneにはレールという概念が存在します。
リリースフローの作業(テスト配信、AppStoreの申請など)を
それぞれをレーンとみなし、提供されているアクションを
組合せてレーンを作成します。
用意されているものだけでも十分ですが
プロダクトに合わせてカスタマイズすることも可能です。
導入方法
基本的にコンソールの指示に従っていくだけで初期設定が完了します。
#インストール $ sudo gem install fastlane #初期化 $ fastlane init #画面の指示にしたがって値を入力していく Your Apple ID (e.g. fastlane@krausefx.com): XXX@XXX.XXX Starting login with user 'XXX@XXX.XXX' ------------------------------------------------------------------------------------- The login information you enter will be stored in your Mac OS Keychain You can also pass the password using the `FASTLANE_PASSWORD` env variable More information about it on GitHub: https://github.com/fastlane/credentials_manager ------------------------------------------------------------------------------------- Password (for XXX@XXX.XXX): ***** +----------------+-------------------------------------------+ | Detected Values | +----------------+-------------------------------------------+ | Apple ID | XXX@XXX.XXX | | App Name | relux | | App Identifier | XXX.XXX.relux | | Workspace | /Users/XXX/relux_ios/relux.xcworkspace | +----------------+-------------------------------------------+ Please confirm the above values (y/n) y Created new file './fastlane/Appfile'. Edit it to manage your preferred app metadata information. Loading up 'deliver', this might take a few seconds Login to iTunes Connect (XXX@XXX.XXX) Login successful +--------------------+-------------------------+ | deliver 1.10.3 Summary | +--------------------+-------------------------+ | username | XXX@XXX.XXX | | app_identifier | XXX.XXX.relux | | metadata_path | ./fastlane/metadata | | screenshots_path | ./fastlane/screenshots | | skip_binary_upload | false | | skip_screenshots | false | | skip_metadata | false | | force | false | | submit_for_review | false | | automatic_release | false | +--------------------+-------------------------+ Writing to 'fastlane/metadata/ja/description.txt' Writing to 'fastlane/metadata/ja/keywords.txt' Writing to 'fastlane/metadata/ja/release_notes.txt' Writing to 'fastlane/metadata/ja/support_url.txt' Writing to 'fastlane/metadata/ja/marketing_url.txt' Writing to 'fastlane/metadata/ja/name.txt' Writing to 'fastlane/metadata/ja/privacy_url.txt' Writing to 'fastlane/metadata/copyright.txt' Writing to 'fastlane/metadata/primary_category.txt' Writing to 'fastlane/metadata/secondary_category.txt' Writing to 'fastlane/metadata/primary_first_sub_category.txt' Writing to 'fastlane/metadata/primary_second_sub_category.txt' Writing to 'fastlane/metadata/secondary_first_sub_category.txt' Writing to 'fastlane/metadata/secondary_second_sub_category.txt' Successfully created new configuration files. Downloading all existing screenshots... Downloading existing screenshot '1_iphone4_1.4.0inc-01.jpg' Downloading existing screenshot '2_iphone4_2.4.0inc-02.jpg' Downloading existing screenshot '3_iphone4_3.4.0inc-03.jpg' Downloading existing screenshot '4_iphone4_4.4.0inc-04.jpg' Downloading existing screenshot '5_iphone4_5.4.0inc-05.jpg' Downloading existing screenshot '1_iphone35_1.3.5inc-01.jpg' Downloading existing screenshot '2_iphone35_2.3.5inc-02.jpg' Downloading existing screenshot '3_iphone35_3.3.5inc-03.jpg' Downloading existing screenshot '4_iphone35_4.3.5inc-04.jpg' Downloading existing screenshot '5_iphone35_5.3.5inc-05.jpg' Downloading existing screenshot '1_iphone6_1.4.7inc-01.jpg' Downloading existing screenshot '2_iphone6_2.4.7inc-02.jpg' Downloading existing screenshot '3_iphone6_3.4.7inc-03.jpg' Downloading existing screenshot '4_iphone6_4.4.7inc-04.jpg' Downloading existing screenshot '5_iphone6_5.4.7inc-05.jpg' Downloading existing screenshot '1_iphone6Plus_1.5.5inc-01.jpg' Downloading existing screenshot '2_iphone6Plus_2.5.5inc-02.jpg' Downloading existing screenshot '3_iphone6Plus_3.5.5inc-03.jpg' Downloading existing screenshot '4_iphone6Plus_4.5.5inc-04.jpg' Downloading existing screenshot '5_iphone6Plus_5.5.5inc-05.jpg' Successfully downloaded all existing screenshots Successfully created new Deliverfile at path 'fastlane/Deliverfile' 'snapshot' not enabled. 'cocoapods' enabled. 'carthage' not enabled. Created new file './fastlane/Fastfile'. Edit it to manage your own deployment lanes. fastlane will send the number of errors for each action to https://github.com/fastlane/enhancer to detect integration issues No sensitive/private information will be uploaded You can disable this by adding `opt_out_usage` to your Fastfile Successfully finished setting up fastlane
テストアプリ配信の自動化
弊社ではdeploygateを利用しており手順は以下のようになります。
fastlaneでは全ての工程を自動化することができます。
テストアプリ配信フロー
1. pod install の実行
2. アプリケーションのビルド
3. プロビジョニングファイルの更新
4. ipaファイルの生成
5. deploygateへのアップロード
Fastfile
fastlane/Fastfileに実行させたいアクションを書いてきます。
initした状態で一通りのものは揃っているので
どういう書き方をすれば良いか迷うことはないと思います。
事前処理
レーンを実行する前の事前処理を書いておくことができます。
- 実行後にSlackに通知できるようにWebhookURLを設定
- cocoapods pod installの実行
before_all do ENV["SLACK_URL"]="XXXXX" cocoapods end
deploygateレーン
deploygate配信用のレーンを新しく用意しています。
アップロードする際のメッセージは最後のコミットメッセージを設定しています。
- sigh プロビジョニングファイルの更新
- gym アプリケーションのビルド
- deploygate deploygateへのアップロード
lane :dg do sigh(adhoc: true) gym(scheme: "relux", configuration: "Debug") message = "relux for iOS\nCommit message: #{last_git_commit[:message]}" deploygate(user: "XXXXX", api_token: "XXXXX", message: message) end
事後処理
レーン実行した後の処理を書くことができます。
ここでは レーンが成功したことをSlackに通知するようにしています。
after_all do slack(message: "Successfully fastlane.") end
Slack上ではこのように表示されます。
レーンの実行
今回紹介したdeploygateはこのように実行します。
$ fastlane dg
とても簡単です。導入前は手動でアップロードしていたのですが
コマンド1つでアップロードできるようになりかなり楽になりました。
deploygateには必ず最新版のテストアプリがあるという状態を保つことができています。
AppStoreへの申請についても自動化することができるので次回紹介したいと思います。
relux iOSアプリに Material Design 風のフォームを導入
relux iOSアプリにマテリアルデザイン風のフォームを導入しました。
マテリアルデザインのライブラリはMaterialKitが有名ですが
見た目がイメージしていたものと異なるのでスクラッチ開発しました。
実際のアプリケーションのスクリーンショットと交えながら紹介していきます。
マテリアルデザインとは?
Googleが発表したデザインガイドラインです。
詳しくはこちらを参照
Introduction - Material design - Material design guidelines
入力フォーム
フォームレイアウト
どのフォームも基本的に以下の要素で構成されています。
- タイトル
- 必須項目マーク
- テキストフィールド
- 下線
- アイコン
- エラーラベル
エラーの表示、非表示でレイアウトの高さがかわらないようになっています。
Androidのサポートライブラリでは高さが動的にかわるようになっていますが
レイアウトがガタガタかわると美しくないのであえて固定しました。
フォームの共通処理
必須項目制御
BOOLで必須項目を設定できるようにしています。
必須項目にするとフォーカスがはずれた際に
自動的に空か判定してエラーメッセージを表示するようにしています。
キーボード制御
AccessoryViewが自動で挿入されるようにしています。
「決定する」を押すとキーボードが閉じます。
キーボードのNext(Enter)を押すと次のフォームにフォーカスするようになっています。
次のフォームが存在しなければキーボードを閉じます。
次のフォームにフォーカスがあたると
自動的にスクロールされるようになっています。
ここの使用感はかなりこだわっってつくっているので
実際のアプリをダウンロードして触ってみてください!
フォームの状態
フォームの状態は以下の3種類です。
disabledは用意していません。
シンプルなデザインなので迷わないよう
disabledにするのではなく表示しないというルールにしています。
最後に
いかがでしたか?
iOSのフラットデザインとAndroidのマテリアルデザインの
良い部分を組み合わせることができたのではないかなと思います。
さらに良いユーザ体験を提供できるよう改善を行っていきます!
おまけ
今まで知らなかったのですがこちらのライブラリも良さそうですね。
github.com
potatotips # 30 (iOS/Android開発Tips共有会)に参加しました!
potatotipsにiOSブログまとめ枠で参加しました!
potatotips.connpass.com
- 会議室は無料で貸出
- 勉強会をやるとピザの差入れあり
らしいのでいつか使ってみたいと思います。
iOS Tipsまとめ
iOSに関連する発表のメモになります。
間違いなどがあれば指摘お願いします。
Proactive Suggestions 発表:nk5さん
※資料挿入予定
- NSUserActivityにmapItemが新しく追加
QuickType for TextFieldが便利そうでした。
このあたりはあまり触れていないので実際に動かして色々試したいです。
(うさぎの汁なし担々麺 美味しそう...)
Siri Kit 発表:Motoki Naritaさん
- Intents Framework と Intents UI Framework を使って実装する
- AppIndentVocabulary.plistにワードを登録するとSiriが解釈できるようになる
- UnitTestを書くことができる
Siri Kitを使ったアプリが楽しみですね。
UnitTestを書けるのが意外でした。
喋って動作確認はかなり恥ずかしいのでこれはありがたいです。
パスワードレスのアプリをつくる 発表:hayashi311さん
- fidoという生体認証の話
- 公開鍵暗号を使ったチャレンジレスポンス方式の認証
- サービス登録時に生体認証を使う
- 生体認証で署名鍵、検証鍵を生成
- 署名鍵を端末で保存
- 検証鍵をサーバで保存
噛み砕いて説明していただいたのでとてもわかりやすかったです。
これが標準になれば幸せになれそうな予感がしました。
デバイス間連携もできるそうです。
Xcode Extensions 発表:y_kohさん
- Xcode Source Editor Extensionsの話
- 開いているファイルを処理することができる
- パレットを表示したりエディタの表示を変えることはできない
まだまだ できることは少なそうですが今後に期待したいですね。
さらに便利になったR.swiftの実力を見るがいい 発表:takasekさん
- Nibの指定などを安全に書くことができる
- NSLocalized Stringsにも対応
- Colorsにも対応
NSLocalized Stringsや画像などはプラグインで入力しているので、タイポ困ったことはありませんがリソースが削除された際にビルドエラーになるのは良いですね。
RIP Xcode Plugin 発表:dealforestさん
Xcodeのプラグインは本当に悲しいです...
しばらくは code sign を消したXcodeでがんばって
Xcode Editor Extensionsを見守るしかないんですね...
Server side swift framework Slimnerの紹介 発表:noppoManさん
- Revel(GO)の2倍
- node.jsの5倍
面白そうなのでちょっと触ってみたいと思いました。
サーバサイドもクライアントもSwiftでできたら幸せ
アプリUIUX事例研究 # 2 TodoMovies
アプリUIUX事例研究
"イケてるアプリ"の"イケてるUIUX"を研究する。
話題のアプリや気になったアプリを触って
良いと思ったものを紹介していきたいと思います。
第2回目は「TodoMovies」を紹介します。
Details
ポスター画像の下部を三角形でマスクして文字を載せています。
これはiPhone6のスクリーンショットなのですが
1画面に収まるように設計されているのが良いですね。
予告動画の再生とシェア導線がきちんと表示されています。
Search
検索画面はこのようになっています。
Watchedにある Star Wars は緑のマークがついています。
これはかなりわかりやすいですね。
Xcodeプラグイン紹介
iOS10は評判が良さそうですね!
未だに触れていないですが時間をみつけて触ってみたいと思います。
本エントリーではXcodeのプラグインについて紹介したいと思います。
Alcatraz
まず、Xcodeプラグインを管理するパッケージマネージャを紹介します。
プラグインのインストールは全てこれで行うのがおすすめです。
alcatraz.io
インストール
ターミナルからコマンドでインストールすることができます。
curl -fsSL https://raw.githubusercontent.com/supermarin/Alcatraz/deploy/Scripts/install.sh | sh
プラグイン紹介
AutoHighlightSymbol
カーソルがあたっているシンボルにハイライトがつきます。
Xcode -> Editor -> Auto Highlight Symbol を
チェックすると有効になります。
ClangFormat
コード整形プラグインです。
Xcode -> Edit -> Clang Format -> Click Format on save
をチェックすると保存時にFormatされます。
保存時だけでなく任意のタイミングでフォーマットをかけたい場合は
ショートカットキーを設定することができます。
システム環境設定 -> キーボード -> ショートカット-> アプリケーション -> +ボタンをクリック
アプリケーション : Xcode.app
メニュータイトル : Format File in Focus
キーボードショートカット : ctrl + i
この設定で ctrl + i で任意のタイミングでフォーマットすることができます。
Formatはデフォルトで以下のようなものがあります。
スタイルはカスタマイズすることもできます。詳しくはGitHubを参照してください。
ColorSenseRainbow
UIColorの指定を簡単にするプラグインです。
UIColorのプレビューが表示されるようになります。
さらにプレビュー部分をクリックすると標準の色選択ポップアップが表示されます。
DerivedData Exterminator
DerivedDataを1クリックで削除できるようにするプラグインです。
Xcode -> View Derived Data Exterminator in Toolbarを
チェックするとこのように表示されます。
真ん中のアイコンをクリックするとDerivedDataが削除されます。
XToDo
ctrl + t で //TODO: //FIXME: などを一覧で
表示できるようになるプラグインです。
以上になります。
紹介したもの以外でおすすめのものがあれば教えてください!
他に良い物をみつけたら追記していきたいと思います。
relux Swift もくもく会 #1 を開催します!
アプリUIUX事例研究 # 1 TALKIE
もうすぐWWDC2016ですね!
発表内容が今から楽しみです。
アプリUIUX事例研究
"イケてるアプリ"の"イケてるUIUX"を研究する。
話題のアプリや気になったアプリを触って
良いと思ったものを紹介していきたいと思います。
第1回目は「TALKIE」を紹介します。
会員登録画面
会員登録画面は通常のフォームではなくチャット風のUIになっています。
LINEやFacebookなどのChatbotも話題になっているので
今後このようなUIが増えていくかもしれませんね。
都道府県の選択もわかりやすいですね。
文字の入力はかなり面倒なのでこのような形の方が良いですね。
詳細画面
画面下部のタブはiOS標準アプリとおなじようなトーンなっています。
青い部分がタップ可能なテキストです。
こちらもiOS標準と同じなのでわかりやすいですが
タップすると赤くなるのが少し気になりました。