iOSとAndroidのtipsを語り合う potatotips 第15回に参加してきたまとめ!
potatotips 15
第15回potatotips (githubはこちら)にブログまとめ枠という大役を背負って行ってきたのでその時のまとめです。
今回の会場は名刺管理アプリのeightで有名なSansan株式会社で行われました。
[iOS] Microframeworks
- MicroframeworksはModelをFrameworksにして開発する手法
- Frameworkを用いれば、固有の名前空間もっていたり、アクセスコントロールがもっていたり、コンパイルが別々に行われるのでビルド時間が短くなったりする
- どうやってframeworkを作るか
- unit testで動作を確認するしか無いので自然とTDDになる
- CIでまわす
- cocoapodsなどのパッケージ管理ツールを使う
- 利点
- 硬いインターフェースを作れる
- 設計も矯正される
- テストを書く必要性がでてくる
- 可能な限りプラットフォームから独立できる
- 悪いところ
- 2週間でリリースするような速度を求められるときなどにはむかない
- ios7はサポートしてない
[Android] Viewの共通化方法まとめ
- Viewの共通化方法一覧
- dimens.xml, colors.xmlでまとめたり
- drawable xml
- styles.xml
- <include />
- customview
- 今日はstyles,xmlと<include />、CustomViewのお話
- styles.xml
- styleは.の後に文字列をつけると継承して使いまわせる
- stylesは複数のxmlにわけて管理するといいかも
- viewのネストが多くなりがちなので<merge />の使い方を覚えよう
- CustomView
- 吹き出しのレイアウトなどの、ロジックが絡むときに使える
- 過剰な共通化によるCosutomView乱立すると、よくわからなくなるので、命名規則などの独自ルールは作っておいた方がいい
- まとめ
- dimens.xml, colors.xml, drawable.xmlはデザインに合わせて使用
- 何度も出てこないレイアウトならレイアウトXMLに書く
- 何度も出て、複数のViewで構成されていなければstyles.xml CustomView
- 何度も出て、複数のviewで構成されていて、ロジックが含まれなければinclude
- 何度も出て、複数のviewで構成されていて、ロジックが入ってくればCustomView
[iOS] WebとiOSアプリでパスワードを共有する
- safariでログインできているので、アプリでもログイン情報を継続できる仕組みの紹介
- アプリでパスワードを入力する画面になった時に、サファリでの情報を読み込んだりする
- 許可されたドメインごとに読み込むようになる
- よめるような手続きで作っても、ユーザが拒否することも出来る
- 複数アカウントにも対応
- SSLはStartSSLを使うことで無料で使える!!
- API側にはドメインをjsonで返すものを作る
- 自動アップデートがあった場合はサーバに一斉アクセスが来る場合があるので注意
[Android] Gradle Tips
hosokawa0825様
- Product Flavor
- 使用異なるAPKを一つのコードベースから作成する
- サーバのURLを環境によって変えたりする
- 問題点1 : strings.xmlなどのリソースが書くFlavorごとに別れる
- 解決策:sourceSetを同じPathにする。サーバURLなど各環境ごとに変更する値はbuildConfigFieldで定義する
- 問題点2:不要なBuildVariantが出来てしまう。
- 解決策:BuildVariantの一部をビルド対象外にする
- Icon versioning
- アプリアイコンにビルドしたブランチ名、コミットHashなどを表示できる
- 注意点
- ImageMagickとGhostScriptを2つをインストールしないといけない。(しかもエラーは出ないのでわかりづらい)
- 上記2つをインストールしてないとビルドが止まってしまう
- インストールされていたらバージョニングするというやり方をしたりする
- plugin側でBuildTypeがreleaseの場合はアイコンを書き換えない処理が入っている
- ImageMagickのコマンドがconvertだと動かない?
[ios] Introducing Tuna
- Tunaとは
- プリントでバッグをビルドし直さない
- 変数を出力するBreakPointとBackTraceを出力するBreakPointを追加できるようになる
- メニューバーからしかつかえないのでショートカットを登録しておくと便利です
- 今後
- Alcatraz対応予定
- そのうち設定画面を作って、breakpointのマクロを組めるようにしておきます
- ショートカットを管理できるようにする
- まとめ
- 快適なデバッグライフを送れるよ!
[ios] カレンダーを自作する
- Frilとジョルテを参考にしてつくってみました
- handMadeCalendar handMadeCalendarOfSwift
- obj-cなら祝日も対応している
- カレンダー計算について
- ボタンをしきつめて、数字をいれるロジックで作った
- 祝祭日の計算ロジック
- ハッピーマンデー法の考慮
- GWとシルバーウィーク
- 未来の祝祭日
- 春分の日・秋分の日
- 参考にしたもの:Wikipedia
- 後々はデザイン対応や、リファクタリング、swift版へのチャレンジをする予定
- 実装詳細:ハンドメイドカレンダー(OS用サンプル)を作りました (解説付)
Androidアプリ滞在時間の計測
- 普通はGAを使う
- Gunosyは自前で実装した
- 方法:Application.ActivityLifecycleCallBacksを使う
- 実装
- activityが発動した時にhashをstackして計測開始するように
- stackしたhashがなくなれば終了ということで計測終了する
iOSで無限バックグラウンドアップロード
- アプリを閉じてもバックグラウンドでアップロードを完了させる
- iosアプリはバックグラウンド動作は3分の制限があるが、NSURLSessionのbackground機能が使えそう
- NSOperationQueueだとメモリにしかデータのらないのでアプリ閉じたらいしぬ
- NSURLSessionを組み合わせて使う
- 永続化JOBキュー
- EDQueueを元に独自実装
- FMDB+SQLiteで永続化
- 前のjobが終わったら次のjobを実行する
- しかしやってみたらDeploygate経由でやったら動かない
- よくドキュメントよんでみたら、端末がLightningケーブルにつながっていてWifiを利用するまで大きなファイルの転送をまつ仕様だった
- Silent Remote Notificationを利用すればできるのでは。。。?
- 画像がアップロードされたらpush通知を使ってクライアントをキックすればアップロードができそう
- まとめ
- 一定間隔でSilentRemoteNotification使えば無限アップロードが可能!
※要チェック:Silent Push / Background Fetch 時の fetchCompletionHandler に渡す引数ごとの挙動の違いを調べてみた
アプリにおける「おもてなし」Tips
- エラーでびっくりさせない
- 可能な限り表示しない
- アラート以外の表示気にしない
- エラーにせずハンドリングする
- エラー、失敗などの激しい言葉を使わない
- 〜がありませんでした、 ~できませんでしたなどにする
- 解決方法を伝える
- どうやったらそのエラーを解決できるかを伝える
- ボタンを押す恐怖を和らげる
- おしたら何が起きるかをユーザの言葉で伝える
- シェアではなく、友だちに教える
- おしたら何が起きるかをユーザの言葉で伝える
- 待ち時間のいらいらを減らす
- 操作には迅速なフィードバックを返す
- いいねをおしたらすぐにUIに反映
- 裏側で通信する
- 操作には迅速なフィードバックを返す
- 頑張って入力されたデータを守る
- 通信が失敗してもデータが消えないようにする
- 前の画面にも変更を反映させる
- 追加したデータが表示されていないと混乱を招く
- リロードすればなおるとかのいいわけはよくない
- 追加したデータが表示されていないと混乱を招く
[iOS] Effective UIScrollView
- ジェスチャーを親Viewに渡してタップするようにする
- 課題1
- scriollviewの裏にあるボタンがタップできなくなる
- -> UIScrollViewのinteractionを無効化にして、panGestureRecognizerを親viewに追加してあげる
- 課題2
- scrollviewを無効にしてしまうのでscrollviewにあるbuttonも無効化される
- -> HitTestでUIScrollViewのタップ判定を無視させる
- この場合はUIScrollViewのinteractionは有効に
- まとめ
- addGestureRecognizerメソッドの利用
- HitTestを調整する
[Android] CircleCIで消耗してみた話
@huin様(kshuin)
- pushしてから10minしないと結果が出ない
- なんとか早くしたく挑戦した
- 時間かかってる処理をまず見つける
- 必要なSDKのインストール、エミュレータの起動、ビルド&テスト
- 方針
- SDKインストールの高速化 -> 2回目以降のジョブではSDK群をキャッシュする
- ビルドテストの高速化 -> disablePreDexオプション付きでビルド
- エミュレーターの起動高速化 -> Robolectric導入でエミュレータ無しでテスト実行
- CicleCIでの処理は環境変数せって+SDKインストール+テスト実行で2~4回めの時間で計測したら早くなった
[iOS] Introducing APIKit
- APIクライアントをswiftでかくのはもったいない
- エンドポイントが存在不明
- パラメータになんでもつっこめる
- 返り値をoptionalだと4パターンになってしまう
- APIKitを使うメリット
- エンドポイントが保管されるようになる
- パラメータを型で制限できる
- enumも使える
- レスポンス結果はちゃんと2パターン
- 網羅性も明らか
- unwrapせずに値を取り出せる
- 値の型はリクエストから推論される
- Genericsを使って実装している
- 失敗時はNSErrorが入る
- Requestプロトコルに適合すればリクエストの定義は完了
- エンドポイントの定義は1箇所だけで済む
- まるでドキュメントをうつしているかのようなソースが書けます!
[Android] GooglePlayへのアップロード自動化を試してみた
cf
tech.vasily.jp
46 Users
60 Pockets
http://tech.vasily.jp/circleci_deploygate_android_app_automation/
- リリース作業で、確認したあとにGooglePlayへのアップロード作業を自動化したい!
- GooglePlayDeveloperAPIを使う
- マージをトリガーにalphaでGooglePlayへアップロード
- alphaからproductionにプロモートすることでリリース完了
- 問題としては各種ライブラリをcircle.ymlにかくのがめんどい
- GradlePlugin化すればCircleCIでに実行も可能ではとおもったら、githubに既にプラグインがあった
- -> gradle-play-publisher
- まとめ
- gradel-play-publisher + CircleCIを組み合わせれば自動でアップロードが出来ます!
[iOS] WatchKitにおけるiPhoneAppとのデータ共有
- WatchKitの処理はWatchKit Extensionで動き、WatchKitがお互いに通信しあう
- データ共有方法 -> AppGroupもしくはopenParentAPplication:reply
- AppGroup
- LocalStorageとNSUserDefaultsで使える
- openParentAPplication:reply
- custom interface controllerからdictionaryでuserinfoというのをわたせて、返り値としてアプリからwatchにreplyinfoというのを渡せる
- 活用例
- 設定値はUserDefaultsを使う
- アプリで保持しているデータはreplyを使って使う
- viewを変えることも出来たりする
[Android] Material DesignなDrawerを実装したい
残念ながらご欠席だったので資料のみの共有になります
[ios]Realmビギナーが知っとくべき内容で打線組んだwww
- Realmの読み方は「レルム」
- RLMObjectサブクラスのプロパティ定義がカラムを示す
- モデルでテーブル定義
- 使えない型で定義すると実行時にエラー
- NSNull/nillで保存できない
- WebAPIを利用した場合、レスポンスにオプショナル項目があると辛い
- 妥協案1:その値があるかどうかのBOOLフラグをもっておく
- 妥協案2:整数ならINT32_MINでありえない値をつっこむ
- NSStringだとnilが保存できてるるとおもったらnilが保存されている
- 主キーはstringか整数でなければいけない
- intだけでなくlongなども使える
- NSDateがミリ秒を保存できない
- バグなのでそのうちなおるかと
- NSTimeIntervalを使う
- ISO8601形式でNSStringで保存する
- メソッドでかえすようにする
- Realm+Jsonが自動でISO8601系行きの文字列をNSDateにしてしまう
- JSONのマッピングルールをMantleのように書ける
- JSONExportのコードはnilを考慮していない
- RLMObjectのプロパティ属性は書かないことを推奨
- NSIntegerじゃなくint64_tを使うべき時もある
まとめ
今回もたくさんのtipsが出てきました。
個人的にはTunaが開発でもすごい役立ちそうなので早速今日から使ってみようかと思っています。
あと、おもてなしの心はかなりぐさりと心に響きました…。
おもてなし精神を考慮しながら開発しようかと思います。