potatotips #58 のiOSブログまとめ枠で参加させていただきましたのブログです。
会場は FiNC Technologies さんでした。
個人的には今月のApp Client Melting PotというFiNCさん主催のイベント以来だったのですが、なんか重大発表でも始まるんかってぐらいおしゃれ会場でした。
以下発表内容です。参加枠としては iOSブログまとめ枠でしたが Android の発表内容に関してもまとめています。
気になるところや間違いなどあればご指摘ください。埋まっていない資料は公開されたのを見つけ次第反映します。
RxSwift - テストスケジューラの解像度について / y.imajo さん
RxSwift で .debounce() をテストする話。
debounce(0.3)なら 3.3 秒のタイミングとかでちゃんと発火されるかとかを調べたい。ただ仮想時間は整数なので現実時間指定の0.3と合わない… →仮想時間に変換すればOK
今からはじめるrobolectric / moriiimo さん
RobolectricでUIテストを書いてみる。 @Config(sdk = [LOLLIPOP])
で sdkのバージョンを指定できる。.start() や .resume() とかでライフサイクルを呼べる。performClick クリックイベントを模することができる
Roomのテストを書いてみたい。書いてみた。context には InstrumentionRegistry.getInstrumentation().targetContext をつかう
アプリ内の絵文字をカスタム絵文字化した話 / RyoIzumi さん
iPhoneでもTwemojiを表示したい。Apple絵文字をちゃんとTwemoji化するのは意外と大変で、家族の絵文字をconvertすると家族分裂したりする。
詳しくはUnicode Emojiのことを勉強してくれという感じなのだが、emojicaというライブラリがあるのでこれが使える。
UILabel や UITextView 上のiOS絵文字をカスタム絵文字に変換できる。
日本語入力で UITextViewのmarkedTetRange が考慮されていないとか emoji 11.0 に対応してないとかあったが、パッチを送ってなんとかした。(emoji 11.0に関しては今送ってるところ)
Flankでテストを爆速にする / Kubode さん
Flank はFirebase Test Lab を並列化するテストランナーで、Android/iOSに対応。導入が結構簡単。
なぜ導入したのか?CIテストに28分とか掛かる… そのうちgcloud(Firebase Test Lab)に18分掛かっていた。
導入した経緯としては、CI/CD Test Night #2 でBitriseの中の人が紹介していたので。
Flankの機能。YAMLによる設定の管理ができる。gcloud公式のYAMLと互換性のある記述が可能。FirebaseTestLabでやってれば移行が簡単。
シャーディング。これがメインなのだが、指定した数に自動でテストを振り分けることができる。各シャードで必ず実行するものを指定したりもできる。 testShards=-1にすると最速だがテスト数*1分の課金が発生し、270個のテストだと4.5ドルも掛かってしまう。いいあたりで調整する必要がある(8とか16とか)。
コストレポートが出せる。テスト結果はHTMLやJUnit の XMLで出せる。
fastlane+Bitriseでやったが、./results/*/をコピーすればテスト結果をbitriseですぐ見れる。
もともとFirebaseを導入していたのでほとんどやることなかった。flank.jarは24MBもあるのでgit管理しない。
Flankでshard=16にしたら28分が8分になった。やったね
CI上で結果が見えやすくなりテスト項目の見直しに繋がった 速くなっただけでなく、未使用コードの削除や無駄なwaitに気づけるなど副次的な効果もあった
導入コストも金銭的コストもやさしいので、iOSにも導入したい
SceneKitでふんわりした影を描画したい / noppe さん
iOS12 から usdz をサポートするようになった。
File アプリで プレビューやAR配置ができる。
Fileアプリで見ると影がきれいについている。これはWWDCで語られていた Contact Shadow(設置感・重なり感を出すもの)だと思われる。これをやってみたい!
SCNLight の castsShadowをONにして、directionalかspotタイプを使う。するとかなりはっきりした影ができてしまう。shadowRadiusというプロパティを使えばふんわりになるがなんか雑な感じ…
さらに調べていると、Contact Shadowとは耳慣れた言葉で言えばAmbient Occlusionのことであるという記述が見つかった(耳慣れたってなんだよ)
SSAO…ScreenSpaceAmbientOcclusionはカメラに生えとって実装できるが、ふんわりしない…ふんわりした影は自前でやらないと無理そう
SCNTechniqueという、マルチパスレンダリングのためnクラスがある。これは画面1回の更新の間に、異なるシーンを複数回レンダリングして合成した結果を表示する機能で、MetalやOpenGLESでシェーダを書くことができる。カメラを2つ配置して、下からの入力を深度に変換しブラーをかけるみたいなのを作ってみたが、モアレ(縞模様)ができたりしてうまくいかなかった。シェーダ真面目に書こうとするとサクッとできなさそう
最終的には、gobo(SCNLightの影を自前の画像で描画する機能?を使って、SCNTechniqueで深度画像に変換→SCNViewのsnapshotでUiimageで取得→ブラーかけて→goboに渡した
これではまだFileの表現に達してはいないが、今までのに比べればまぁまぁ見れるものができた
MDCのBottomAppBarのShadowの実現方法 / HiroYUKI Seto さん
OSがShadowを描画する条件。
- Android 5.0↑
- elevation が 0 より大きい
- Viewのアウトラインが四角形か、凸図形(凹んでいる部分がない=CONVEX_PATH)
BottomAppBarは明らかに凹んどるけど影がついてる。これどうしてるの
MaterialShapeDrawableを使ってるっぽい。でTopEdgeがMaterialShapeBottomAppBarTopEdgeTreatment。これはarcでくぼみを表現していて、TreatmentのgetEdgePathを見れば分かる。
setShadowCompatibilityModeをSHADOW_COMPAT_MODE_ALWAYS にすればOSがつける影以外が使える。ShadowRendererというのを使ってて、便利じゃんと思ったが、残念ながら @hide (IDE上で見えなくする?)や @Restricto(LIBRARY_GROUP) (ライブラリ内から呼ばないとwarining出る的なやつ?)アノテーションがついており、リフレクションとかしないと使えない。
スクリーンタイムと仲良くなる / 5mingame2 さん
iOS11から純正のカメラアプリでQRコード対応している
ところで、スクリーンタイムというiOS12からアプリの使用状況を集計したり、時間制限をかける機能がある。時間制限が掛かっているとアプリ起動直後に落ちることがわかった。
どうやら制限掛かっていると、AudioSessionのコンテキストが取得できてない様子 didFinishLaunchingWithOptions: で初期化処理をしてたのだが、ここで落ちてる感じだった
UnityでiOSアプリをビルドするとXcodeのプロジェクトとソースが生成される。これを参考にした。するとここら辺 applicationDidBecomeActive: に書いてたのでそこに移動した。
いまさらWorkManager / どくぴーさん
適宜実行されたり実行されたことの保証が必要なバックグラウンドタスクを扱う。compileSdkVersion 28。
シンプルでこれまで自前で実装しないと行けなかった要件、たとえばAPIレベル、Play Servicesの有無によるJobScheduler/AlermManager/FirebaseJobDispatcherの使い分け、バッテリ・通信状態などに合わせた処理などとかを自動でなんとかしてくれる
Workerについて。Worker を継承したクラスを作る。override fun doWork() 内で必要な処理を記述し、成功・完了に応じてWorker.Result.success/failureを返す(これ以前は定数だったので codelabs のコードを直接使うと死ぬ)
WorkRequestについて。Workerへ実行に必要なデータを与える(DataクラスをbuilderクラスでbuildしたものをsetInputDateでsetする)。注意点としては、でかいデータは与えられない。一度だけ実行できるものと定期的に実行させるものがある。
生成したWorkRequestの実行はWorkManager#enqueueするだけ。
複数のworkを連結したいときがある。WorkManager#beginWithでContinuationが返ってくるのでthenで連結とかすると、重複することがある。なのでWorkManager#beginUniqueWorkに変更する。でExistingWorkPolicyで実行中の処理に対する処理を変更する。
Workの実行状態を制限したいときは、実行時に制約(通信状態や、充電中かどうか‥など)が付けられる。uniqueIdを与えたContiuationはキャンセルできる。LiveDataとの連携、Rxサポートもある。
UIViewPropertyAnimator and Easing / TachibanaKaoruさん
UIVIewPropertyAnimatorはiOS10〜なのでそろそろ入れてもいいんじゃないという感じ。
UIView.animate は都度アニメーションのようすを設定するが、 UIViewPropertyAnimatorは動きを宣言して、好きなタイミングで実行するようになった。イージングが簡単にできる。
制御点を設定できるのだが、結構難しい。カスタマイズするときはデフォルトで定義されているやつをちょっといじるのが良さそう。
既存のライブラリのパラメータを拝借してイージング用のUIViewPropertyAnimatorをいっぱい生やしたextensionを書いたので難しさ感じる人は使ってみてください。
既存プロダクトにダークモードを実装した話 / Hakuto Suzuki さん
ダークモード、目に優しいだけでなくコンテンツを目立たせることができる。(画像がいい感じに見える)
夜間の利用ユーザーが多いので導入した。CVR にも良い影響があった。
実装は AppcompatDelegate.setDefaultNightMode(AppcompatDelegate.MODE_NIGHT_YES) を設定。
WebViewへの画面遷移を挟むとなぜかDarkmodeじゃなくなるというバグがあった(GoogleのIssue Trackerに登録されている)遷移する前にWebViewの初期化を再度行うと回避できるっぽい
WebView怖い
Hint of “Passcode Lock” Screen and Logic (with LocalAuthentication). / fumiyasac さん
www.slideshare.net
パスコードロック画面作った。設計を紹介。
バックグラウンドに入るタイミングで上に画面かぶせる感じ。AppDelegate のライフサイクルでなんかやってる場合は処理がかち合うので注意という感じだった
詳細はQiitaで:
5プラットフォームをサポートしているプッシュ通知SDKをFCMに移行した話 / konyavic さん
SDK開発者として実装に必要なステップを減らし、ドキュメントをシンプルに保つことを意識している。
アプリのグロスのためのSDKを作っていて、プッシュ通知、ABテスト、アナリティクスなどが利用できる。5プラットフォームに対応している。このSDKを2019年4月までにGCMからFCMに移行しないといけないことになった。
トークンの取得部分を変更することになったが、FCM、Tokenの取得メソッド多すぎ問題。FirebaseInstanceIdのgetToken()というのがあるがdeprecated。getInstanceId()は推奨されているけど新しすぎて、SDK利用側が利用できないかもしれない。結局はgetTokenなどでも使えるAPIは維持しつつ、getInstanceId()でtokenを取得するようにした。
つかおう!Storyboard / coffeegyunyu さん
コードでUI書いてるとつらいときある。StoryBoardを使うと、iPadのときの文字サイズ、横向きにしたときの指定などが簡単に指定できる。
これにより、iPhone/iPadや横向き対応はもちろん、Container View、UISplitViewController、Pop Over、Form sheet、Slide Over、Split View、iPad ProのPortrait+SplitView+UISplitViewController、tvOS…などなど色々な UI の表示形式に対応することができる。
Visionとモザイクで遊んでみた / ochimさん
WWDCの資料とクラスメソッドのブログ見て実装した。VNDetectFaceRectanglesRequestで顔取れる。boundingBoxに位置が入っている。この座標系は左下起点のやつでUIKitと違うので注意。
CIFilterを使うとモザイクかけれる。boundingBox使うと顔だけモザイクかけれる。
感想とか
最近へとへとになりながら会場向かってへとへとになりながらメモりがちで懇親会の頃にはへとへと度高めだけど最終的には懇親会でいい感じに刺激受けれるしやっぱり今回も色々知らないこと知れたりして良かったな〜ってなるので良い