kumamotone’s blog

iOS/Android アプリエンジニアです https://twitter.com/kumamo_tone

potatotips #52 に参加しました (iOS, Androidブログまとめ)

potatotips #52iOSブログまとめ枠で参加させていただきましたのブログです。

会場はFOLIOさんでした。

f:id:kumamotone:20180621193041j:plain

f:id:kumamotone:20180621182347p:plain

最初から FOLIOGoogle の著名なスピーカーの発表が決まっており、申し込みは大人気でした(当日の 18:30 に撮ったキャプチャ。+59 人キャンセル)。

個人的にも気合を入れて臨んだ回だったが、発表陣も異様に気合が入っており、明らかに5分ではない分量のスライドだったり、理解が困難なマニアックでハイレベルなトピックが続出するという状況が、22時ごろまでひたすら続きブログ枠の私は完全に精神が崩壊した

そんなわけで当日にまとめきれず遅くなってしまいましたが、別に溜めたからといってブログのクオリティは上がったりしないんですよね…つらい…

以下発表内容です。参加枠としては iOSブログまとめ枠でしたが Android の発表内容に関してもまとめています。

基本的に発表内容どおりですが、一部、個人的に理解しやすいように勝手に順番を並び替えたり、補足の情報を加えたりしているため、実際の発表内容と違う部分があります。気になるところや間違いなどあればご指摘ください。埋まっていない資料は公開されたのを見つけ次第反映します。

Room のできるまで 〜InvalidationTracker 編〜 / yaraki さん

Room は AndroidSQLite をラップするORマッパー。

@Dao
interface UserDao {
  @Query("SELECT * FROM User")
  fun all(): LiveData<List<User>>>
}

みたいな感じに interface で定義できる。

この User の変更の通知を受け取れるわけだが、 Room は SQLite からどうやって通知を受けているか?

  • 候補1: DAOから通知する
    • 書き込みメソッドの実装はRoomが生成しているので、自分が生成しているコードの中から通知することはできるはず
    • ☓ execSQL で直接クエリを投げたときにも対応できないし、トリガーにも対応できない
  • 候補2: SQLite拡張機能を使う
    • void *sqlite3_update_hook という、何か変更があったときに通知を受け取れる C 言語のAPIがあって、完璧じゃんとなるが、
    • Android ではAPIが開いていない
  • 実際に採用した方法: トリガーをつかう
    • 変更ログのテーブルを作っておき、各テーブルに変更があるたびに変更ログに記入されるようなトリガーを仕掛ける。トランザクション終了時にログを確認して(Roomではすべての書き込みはトランザクションで処理される)、Observerに通知する。

Livedata でテーブルに変更があったときに通知を受け取る場合、 invalidationTracker を使えば良いです

WWDCのセッションから、パスワードのAutofill、エクステンションの紹介 / kishikawakatsumi さん

speakerdeck.com

Web では iOS12 以前から使えた機能だが、パスワードの自動生成というのができるようになった。 勝手に強力なパスワードをSafariが考えてくれて、Keychainに保存しておいてくれる。また、iOS12 から、Safari を使っていれば 2段階認証で SMS で受け取ったコードを自動入力してくれる。

アプリ開発者が対応すべきことはなにか。 AccosiatedDomains というのを設定する。

Textfieldをつくって、Content Type に Username と Password を設定する。すると入力時に鍵のマークが出る。ちゃんとAccosiatedDomainsが設定されていれば、候補が鍵マークの左に出る。鍵マークをタップして、KeyChainから選んで入力することもできる。

Automatic Strong Passwords。iOS12からの機能で、サインアップをするときにOSが自動的にパスワードのサジェストをしてくれる。

Content Type を New Password にすると、これはサインアップ画面で使われるものだという認識をしてくれて、自動でパスワードを考えて強いパスワードを設定してくれる。Keyboard の type を email にすると、emailになるし、デフォルトだとユーザー名っぽい感じになる。

サーバーの方のパスワードのルールと合わない場合は、 Password Rules Validation Tool というのを使うと、 IB Password Rule (セッションではIBで設定できるよと言っていたが、今のところコードからしか設定できない)

困っていることとして、パスワードを保存してくれるタイミングが全然わからない たぶん自動で保存してくれるはずなのだが‥

Two factor auth も同じような感じでできる(関係ないSMSにも反応する)。対応コストは小さいので、対応しておくと離脱を防げて良いのでは。

KotshiからMoshi-codegenに乗り換えた経緯 / duane0728 さん

speakerdeck.com

今年の2月のpotatotips で、moshi-kotlin がリフレクション使っていて遅くて、Kotshiを使ったら早くなったという話を @magie_pooh さんがしていた 。

Moshi-codegen もそうで、リフレクションフリー。Kotshi とどちらを使えば良いのか?

  • 速度
    • 速度の検証、0.2MBのjsonのパースを20書い行った時間の平均msecを測った 大差なし
  • 安定性
    • codegen のほうにバグがあるのに気づいた nonnull な string に null が入ってしまう
    • ただ最新版 Kotshi でも同じバグが起きている
  • 将来性
    • Moshi-codegen は Moshi 本家がオーナー
    • Kotshi の issue で Kotshi の作者が deprecated になるかもと言っている

これからcodegenを導入するなら、kotshiも導入していない場合、最初からmoshi-codegenのほうが良さそう。

How to Manage Edge Gestures / TachibanaKaoru さん

speakerdeck.com

画面をなぞるときの操作には3つある。

  • Pan
  • Flick
    • HIGいわく、速くPanすること(ので実質パン)
  • Swipe
    • HIGいわく、画面をなぞること

Edge Pan Gesture というのはエッジからジェスチャーするやつ。iOS7あたりから UIScreenPanGestureRecognizer で取ることができる。

これですべての Pan Gesture を扱えることを期待したいが、実際には、画面上部や画面下部はシステムジェスチャ(通知センターが出る)が優先されてしまうという問題がある。

f:id:kumamotone:20180715182309p:plain

prefferedScreenEdgesDeferingSystemGestures というiOS11から使えるメソッドをoverride して方向を返す実装を書けば、システムジェスチャを一回ブロックすることができる(ベロみたいなのが出て確認できる感じ)。たとえばデレステ音ゲー)はこれをやっている。

HIG を読むと、やるなとは書かれている。でもゲームとかだとしょうがないよね。

Kyashで使っているTutorial Library / konifar さん

speakerdeck.com

世の中に出ているチュートリアルライブラリ下記の3点が不満で、ライブラリを作った。

不満な点と、作ったライブラリがした対応は以下の通り。

  1. ハイライト部分に角丸のものがなかった
  2. interpolatorやdurationをセットできる
  3. ハイライト部分のアニメーションしか対応していない
  4. interpolatorやdurationをセットできる
  5. テキスト部分のレイアウトをカスタマイズしにくい
  6. setMessageLayoutResId で作ったレイアウトをセットするだけ

よかったら使ってみてください。

github.com

enum as Option / r_plus さん

speakerdeck.com

Swift には Optionset という複数のフラグを管理するためのプロトコルがある。こんな感じで実装して使う。(developper.apple.com/documentation

struct ShippingOptions: OptionSet {
    let rawValue: Int

    static let nextDay    = ShippingOptions(rawValue: 1 << 0)
    static let secondDay  = ShippingOptions(rawValue: 1 << 1)
    static let priority   = ShippingOptions(rawValue: 1 << 2)
    static let standard   = ShippingOptions(rawValue: 1 << 3)

    static let express: ShippingOptions = [.nextDay, .secondDay]
    static let all: ShippingOptions = [.express, .priority, .standard]
}

Int 型の rawValue を数値ではなく、1か0のフラグを表す bit の列として使う。

使う側はlet option: ShippingOptions = [.priority, .standard] みたいな感じで定義して、 if option.contains(.priority) 判定できる。

Foundation でもよく使われている(DispatchQueueのAttributesなど)。

この OptionSet、単なるオプションを判定したいだけにしては記述が面倒ではないかと思うようになってきた。

そのような場合にはOptionSetを使う必要はくて、シンプルにenumを定義して管理すれば良い。複数のオプションの判定をしたい場合は可変長引数にすれば良い。こうすると、 OptionSet を引数にとった場合と 可変長引数の enum を引数にとった場合の実装側の書き方は一致する。

ただ、 OptionSet にあった Union の処理などができないので、そのような複雑な要件の場合には OptionSet を使ったほうが良いかも。

XML Object Mapping / hiroyuki_mori_1217 さん

speakerdeck.com

Swift4 で Codable が追加され、 JSON をモデルに簡単にマッピングできるようになった。

Java はこういうの得意で、 Android には Gson, Jackson, Moshi, SimpleXML... など色々ライブラリある。

これらのライブラリは、空のインスタンスを作って後からセットするというのが基本のロジックであるが、Kotlinでは「イミュータブル」で「非Null」なオブジェクトを扱うため、この方法は相性が悪い。

これを克服しているのが Moshi であるが、 XML には対応していない。仕方ないので、仕事で XML のマッパーを作った。

自分で作る場合には3つのアプローチが考えられる。

Reflection

f:id:kumamotone:20180715185728p:plain

型パラを受け取って内部構造を監査してオブジェクトグラフを作ってオブジェクトグラフの末端からインスタンスを作っていく。

これは楽でいいが、Reflection は遅かったりしてあまり好まれない。

APT

javac にクラス追加するチャンスがある。データクラスがあった場合に目印としてアノテーションをつけておいて自動生成する。重要なのは名前に規則性があるところ。

拡張性高めで Reflection でないのは良い。

Transform API

techblog.yahoo.co.jp

3つめはTransform APIなのだが、既存の処理を修正することができる 難読化しても影響がないが、超めんどくさい。記事を書いたのでそちらを参照してください。

作ろうぜORマッパー

GDPRについて / yoichitgy さん

GDPRとは何か?ヨーロッパに住んでいる市民の個人情報を適切に扱うための決まり。

データ取得と用途について明示的な同意を取得、情報漏えいや不正アクセスが会った場合は3日以内に通知するとか…

個人情報には、氏名住所は当然として、位置情報やクッキー、病歴など…色々ある。

違反すると全世界での売上の4%、最大25億円を支払わなければならない。EEAのユーザーが対象で、今年5月25日以降からすでに有効 こわい

Crashlytics レポートのユーザ情報、これ危険。レポートで個人情報 が見れてしまう。オプションで見れないようにできますが、注意が必要。

今年のWWDC2018から、ユーザーの行動記録を取る場合は視覚的に明示して同意を取らなければならないというのが書いてある。(2.5.14) 注意が必要。

Tips for Bitrise Android / shaunkawano さん

もともと Circle CI を使っていたのだが、問題としてメモリが足りなくて落ちる、独自のスクリプトを書かないといけないという問題などがあった 今は bitrise を使っている

メモリ不足でなやむことはなくなった、独自のシェルスクリプトに関しては fastlane で解決

tagが切られたときになにかしたい、bitrise.ioのときにはymlでやってたのだが、問題があった。

たとえばタグが切られたタイミングでGithubのドラフトリリースを作って、file-downloaderという機能を使って、KeystoreとGradleのファイルを落としてきてさもローカルで署名してるみたいにできる

fastlaneのほうにはset_github_releaseというレーンがあるのでそれでできる。今後は gradle ファイルのキャッシュなどをやりたい

bitrise Fastlane, file-downloader, おすすめ

Turi Createを試してみる / tattn さん

speakerdeck.com

Turi Create は Apple が買収した Turi という会社

CoreMLのモデルを出力できる 実装済みのアルゴリズムや調整済みパラメータを使って特定の問題を解くという思想で、Create ML の思想に近い

画風変換の学習に必要なデータは、Contant Images と Style Images

github.com

High Sierra でも動く。モデルを続きから学習される機能が現在ないので作って欲しい… 現在対応する気はなさそう

Colaboratoryでも使える (apt install で必要なものを入れられたり、GPUが無料で使えたりして良い)

Android P - Restrictions on non-SDK interfaces / operandoOS さん

speakerdeck.com

非 SDK インターフェースの制限  |  Android Developers

Android P から non-SDK へのアクセスに制限ができるようになった。

リフレクションとか使ってアクセスするようなフィールドやメソッドは、使うと落ちる場合がある。直接リフレクション、またはJNI経由でnon-SDKを使用する場合に適用される。

しかしすべてのnon-sdkがそうなるのか?と言われればそうではない。light-graylist、dark-greylist、blacklistという風に区分けされている。

light-graylist はまだ普通にアクセスできる。dark-greylist は targetSDK によってはアクセスできない。blacklist は targetSdkVersion に関係なくアクセスできない。non-SDK はそもそも使わないほうがいいが、今後はもっと気をつけましょう

見落としがちなVoiceOver対応 / jkatayama さん

speakerdeck.com

カスタマーサービスへ、「アプリ内のほとんどがVoiceOver対応していてありがとう、でも一部使いものにならないよ」という問い合わせがきた

なるほど、しかし VoiceOver なんて実装した覚えはない‥

調べてみると、 VoiceOver でほぼ対応されていて、UILabel,UIButton, TableView の Cell の内容は読み上げてくれるようだった。

しかし、UIButton で画像だけ、のような場合にはリソース名がそのまま読み上げられてしまう。

設定は簡単で、Interface Builder から、 Accessibility > Label にテキストを指定すると良い。

VoiceOver で読み上げられる内容を逐一確認するのは大変だが、 Accessibility Inspector を使うと、カーソル当てると Quick Look が見れて、読み上げられるテキストが確認できて便利である。

What’s new in Google Play Billing / ymnder さん

speakerdeck.com

Google Play Storeのアプリと、Billing Library に変更があったので変更点の紹介。

Play Storeアプリでは、定期購入コンテンツのリコメンドや、何の定期購読コンテンツを購読するか管理する画面が使いやすくなりました。

また、Deep Link によって、我々が作ったアプリから Play Store アプリの管理画面に直接遷移させることができたり、ユーザーが定期購読コンテンツを解約するときに理由を聞いたりできるようになりました。このアンケートの分析結果は Play Console で見ることができます。

Billing Library では、以下のような変更があった。

  • 定期購読のプランを月の途中で変更することができるようになった
    • proration (編注: 比例配分) modeが指定できるようになった
  • launchBillingFlow()を行ったときに、失敗時にもレスポンスを受け取れるようになった

proration mode には以下の 3 つのモードがある。

  • IMMEDIATE_WITHOUT_PRORATION
    • 追加請求なしで移行する
    • 2ドルのプランを月初めに購読開始して、月途中で3ドルにしたとしても、その月は2ドルのままの太っ腹モード。
  • IMMEDIATE_AND_CHARGE_PRORATED_PRICE
    • 日割りで追加請求を行う
    • 2ドルのプランを月初めに購読開始して、半月後3ドルにしたら、2ドルの半分の1ドルと、3ドルの半分の1.5ドルで、その月の請求は2.5ドルになる。
  • IMMEDIATE_WITH_TIME_PRORATION
    • 既に支払った分をクレジットとみなし、日割り計算で使い切ったら新しい課金サイクルで課金が開始される
    • 2ドルのプランを月初めに購読開始して、月途中で3ドルにしたら、1ヶ月未満で次のプランに切り替わる その結果、月途中から新しいプランの課金サイクルが始まったりする

少々ややこしいが、スライドに図解がある。

Swiftで高カインド多相 / inamiy さん

speakerdeck.com

型コンストラクタは「型」を引数に取り、「型」を返す。 カインドは「型の型」。 高カインドは「カインド」を引数に取り、「カインド」を返す。

Swift 4.2 現在、高カインド関数には対応していない。Kotlin では ARROW というライブラリで Functor, Applicative, Monad などの基本的な typeclassをサポートしてる。

github.com

Swiftで高カインド関数を実現するにはどうすればよいのか?

qiita.com

Qiitaに記事があるが、どれも Lightweight Higher-Kinded Polymorphism という論文が元になっている。この論文を元にライブラリ作った。

github.com

これによって Array から List への自然な変換ができたりする。

let list = [1, 2, 3].kind
               .naturalTransform {
                    List($0.value).kind
                }
               .value

list == List.cons(1, .cons(2, .cons(3, .nil)))

Pay attention to the HUGE logs / Ryo Sakaguchi さん

端末内に存在するデータをサーバーに送信する機能を開発していて、データの規模を聞くと、1000件ぐらいだった。長めのbackground jobになるなという感じ。

この機能を実装するために、I/Oで発表された WorkManager を使おうと思った。Worker を継承したクラスを実装して、インスタンスにenqueue するだけ。あとは適切なサイズにデータを加工すればOK。

しかし動かしてみると、 byte[]-> String でOOMで死んでた。forkして出力するログサイズを制限できるパッチを当てたものを使用することで回避した。StethoもRequestBodyが巨大で死んでたりしたがまだ対策できていない。

これが参考になった

in.fablic.co.jp

めっちゃでかいログには気をつけましょう。

Contributing to Swift in WWDC / kitasuke さん

WWDC、Technology Labs というのがある。OSSをあまりやってこなかったAppleだが、ここではエンジニアと話できる。

いろんなLabあるので色々質問できる Swift Open Hours に行った。2日目以降は暇そうだったので色々聞けて良かった。

ラボでは、事前に用意してきた Bug report と、それに対してこういうプルリクを出そうと思うのだが、みたいなことを話して合意を取ったりした。これがめちゃくちゃ良かった。

Swift Open Source Workshop by try! Swift San Jose でワークショップあったのでプルリク出せた。

github.com

Hey Guys, I am... / mhidaka さん

エンジニアリングマネージャーをやるという話。

マネージャー、最初はあんまり興味がなかった。エンジニアリングに集中したいという気持ちがあった

しかし組織の急拡大により、ミドルマネージャーが足りない問題があった。Androidエンジニアのマネージャーがいない。適切なアサインが難しい。技術的な評価が難しい。施策の選択と集中が難しい。

ということでエンジニアリングマネージャーをやることになった。エンジニアリングマネージャとは技術に責任を持つ職能。お試しでというエクスキューズがあるのでやっていけている。人間なのでコミュニケーション、働きやすさが大事。どうすればモチベーションが上がるのかとか教えてほしい。

現在のところは、Slack, スプレッドシートをやっている。俺に任せていけという感じ。

Hey Guys, I am an engineering manager.(タイトル)

Video decode on iOS. / noppe さん

speakerdeck.com

透過動画再生ビューライブラリを作っている。

透過動画とは何かというと、こういうやつ。(引用元: Kitsunebi/animation.gif at master · noppefoxwolf/Kitsunebi · GitHub )

f:id:kumamotone:20180623202531g:plain

2つ動画ファイル用意してあげて、マスク合成して描画している。

今日はビデオファイルのデコードについて話す。ビデオファイル、それはコンテナの集まりであるが、デコードとはメディアコンテナを再生できる状態にすること。

コーデックの違いによって圧縮率などが変わる。AVAssetReader, VTDecompression ffmpeg などの方法がある。

これらのフレームワークでは、内部でOS/端末のデコーダの実装を利用しているのだと思う。OSや端末によってサポートが異なるので注意。たとえばHEVCは一部のチップでしかハードウェアデコードをすることができない。

対応コーデックの確認をすることが今のところできないように見える。AVSessetReader を使うと対応コーデックであればコーデックを意識せずにできるので簡単。

VTDecompressionSessionはもっと低レイヤーなやつで、やや複雑だが柔軟性は高い。特徴としては以下のようになる。

  • ストリーミングでもキャプチャが取れる
  • AVAssetReaderにバグが有っても大丈夫
  • 分散してエンコードしたいときとかに便利
  • エラーチェックとかちゃんとしないといけない

VTDecompressionSessionの流れとしては

  • h264/avcを分割
    • nal file format
  • 映像が含まれるチャンクを取り出す
    • nal unit type は ISO/IEC 14496 に定義
  • VTDecompressionSession を生成
  • チャンクをSession にわたす
  • デコード済みのImageBufferがコールバックに返される

サンプルはgithubにあります

感想とか

ハイレベルなトピックが多く本当にエキサイティングだった。言わずもがな、勉強になったし素晴らしい会でした。

懇親会ではアプリ界の名立たる著名人とコンタクトを取れる貴重な機会であったが、

ブログのために情報の濁流を整理するのに疲弊していた私は、知人とばかり話し、挙げ句シラフであるにも関わらず

「もう東京で消耗しすぎたから1ヶ月ぐらい何もかも忘れて海外に行きたい」

「どうしたら楽してお金が手に入りますかね?」

といった生産性のない話題ばかり降っていた。

これらの話題に、懇親会で嫌な顔せずに応えてくださった優しい方々にこの場を借りて感謝いたします。

potatotips #51 に参加しました (iOS, Androidブログまとめ)

potatotips #51iOSブログまとめ枠で参加させていただきましたのブログです。

f:id:kumamotone:20180523232304j:plain

会場はCAMPFIREさん!渋谷ヒカリエからすぐという超好立地なのに道に迷ってギリギリになってしまった…

f:id:kumamotone:20180523232317j:plain

写真撮り損ねて閉会後になってしまったけど会場の写真 芝あって良い雰囲気

以下発表内容です。参加枠としては iOSブログまとめ枠でしたがAndroidの発表内容に関してもまとめています。

間違いや気になるところなどあればご指摘ください。埋まっていない資料は公開されたのを見つけ次第反映します。

Firebaseで頑張ったこと / nakajijapan さん

Presentations by nakajijapan // Speaker Deck

Firebase Authentication、Tokenの有効期限が1時間であることを考慮して実装しなければならない。getIDTokenForcingRefresh() を使ってリフレッシュすることになる。

retry処理をRxSwiftのretryWhenで実装していた。ただ成功しても失敗しても.nextして.completed してしまっていたので、うまく行ってなかった。

ちゃんとエラーハンドリング実装したら動いた。FirebaseもRxSwiftもちゃんと理解して使おう。

モバイルアプリための通信デバック入門 / imota さん

Presentations by simota // Speaker Deck

通信デバッグのためのHTTPプロキシを紹介。

FiddlerWindowsユーザー向け。Windows使っているならこれがおすすめ。Charlesは無料版だと時間制限がある。

mitmproxyというPythonで書かれているやつがあって、おすすめ。pipで入る。TUI、GUICUI版がある。SSLで暗号化された内容でも、内容を見たり、スクリプトを書いて書き換えたりすることができる。

App Protection ( iOSアプリからVPN接続の検出をする ) / noppe さん

speakerdeck.com

Charles for iOS 出ましたね

うっかり Charles 起動したまま Twitterアプリ開いちゃったんですけど、Charles開いてる状態では読み込めなくしているっぽい。これどうやったら再現できるだろうか?

Charlesは自体は、NetworkExtensionを使ってVPNコネクションを張り、これを使ってIPトラフィックがトンネリングできるという仕組みなのだが、再現する方法は割りとシンプルで、

CFNetworking.frameworkCFNetworkCopySystemProxySettings() という古くからあるものでプロキシ設定が取れる。

CFDictionary という型で返ってきて、__SCOPED__tun という文字が含まれる設定はトンネリングされているものなので弾いても良いのでは?という仮定で実現することができた

コードは公開しています↓

github.com

What's CodeSigning / scenee さん

Presentations by Shin Yamamoto // Speaker Deck

CodeSigningとは?公開鍵暗号方式で、電子署名を付与すること。これをやることで、開発者自身が作成したアプリケーションだということを保証する。

署名はどこに保存されている?Mach-O(実行ファイル)だと CMS形式で署名が埋め込まれている。

Provisioning Profileはアプリプロセスに権限等リソースを提供するためのファイル。これもCMS形式

App起動時にMach-Oの署名情報と、Provisioning Profile を照合しているので、開発者自身が作成したアプリケーションだということを保証できる。秘密鍵がIdentity、公開鍵がProvisioning Profileにあたる。

ほか細かいTips(Provisioning Profileの中身を確認するコマンドなど)

Flutter 入門 / toshihirooya さん

speakerdeck.com

Google が作ったクロスプラットフォーム開発フレームワーク Flutter の紹介。DartAndroid Studio で書けるぞ!

例を紹介。 void main() => runApp(new MyApp()); から始める。 StatelessWidget な MyApp でアプリタイトルとかテーマとか設定する。MyApp から StatefulWidget なクラスを呼んで State を表示する。宣言的な感じになるのでMVVMのVMっぽいイメージ。

今年の I/O の内容だが、 FlutterFire というFlutter用のFirebaseプラグインというのがあってよさそう

github.com

Flutter、素早く両OS開発できる可能性に溢れている 期待!

あると便利な動作検証用機能 / 5mingame2 さん

www.slideshare.net

前回のpotatotips iOSで紹介した、C++(Cinder)でゲームを作る話の続き。

作ってるゲームで動作検証用に付けてる機能を紹介するよ

  1. print機能
  2. asset機能
  3. 一時停止・コマ送り機能を付ける
  4. 表示抑制(切り替え)機能 ゲーム画面ではなくUIだけ動作したいとかその逆とか
  5. ソフトリセット機能
  6. macOS固有の読み込みパス変換 プリプロセッサで頑張っている
  7. 画面解像度一発変更機能 Release ビルドでは消滅する
  8. リアルタイムUI調整機能 これも Release ビルドでは消滅する

別になくてもゲームは作れるが、こういうのは作ると捗る!

Remove Unused Resources / konifar さん

speakerdeck.com

Android Lint の unused resources、ウソをつくので使えない とくにdatabinding とか使っていると、こいつの言うとおり消してくとビルド通らなくなってつらい

でも不要なリソースは消したい… いつかなおると思っていたが、いつまで待っても出ないのでGradleプラグインを作った

github.com

実行するだけ。小さなプロジェクトだとすぐ終わるが、大きなプロジェクトだと、やはり時間がかかってしまうこともある(5分とか)。gistに貼っているスクリプトを定期実行すれば定期的に消せる。

gist.github.com

オプションが2つあって、1つめはサポートされてないリソースファイル、たとえばtext_appearanceの <style> とか消したいとき、createXmlValueRemover()関数でカスタムの設定を書ける。

2つめは excludeNames に設定すると、除外できる。

投げ銭アプリを会社で作っているので、消えた行数を目安に投げ銭してもいいのよとのこと。

Xcode Templateを使ってチームで生産性を上げる / ngtk さん

speakerdeck.com

Xcodeにテンプレート機能がある。一般に、テンプレート機能は共通の記述を書かずに済むようになるので、生産的。

もちろん protocol extension や コード自動生成をまっさきに検討するべきだが、残る温かみをテンプレートでやるということもできる

ただXcodeのテンプレート、カスタムで追加する方法や共有する方法が公式に書いてなくて分かりづらい‥

テンプレートファイルは、適切な位置に __FILEBASENAME__.swift TemplateInfo.plist とか決まった構成で置くことになる。

gitとかで共有したテンプレートファイルをここに置けば良いのだが、結構込み入った場所にあるので、スクリプトを書いた。さらにこれだと使いづらいのでコマンドにした。 brew で入れることもできる。

github.com

Visual Studio App Centerの始め方 / nakasho さん

www.slideshare.net

Visual Studio App Center というMS製 CI/CDツールの紹介。HockeyAppのリブランディングになる。

Android/iOS, UWP, macOS(Preview)に対応していて、Github/Microsoft/Facebook/Googleアカウントとかでログインできて、Visual Studio Team Service, Github, Bitbucketに対応、みたいな結構手厚い感じ。

クラッシュ情報の取得や、Visual Studio Team Services, Github, Jiraと連携してクラッシュ時にチケット起票したり、アナリティクス機能あったり、Flutter向けのプラグインもある!すごい!

ARKit 表示改善 / satoshi0212 さん

Presentations by satoshi0212 // Speaker Deck (基本的にデモベースの発表だったので資料上がらないかもです)

ARKit, 段階を分けて工夫してみたのでサンプル7つを見てもらいたい

  1. ライトなし 単に丸が表示される
  2. autoenablesDefaultLighting = true にする 影がついていい感じ
  3. CIFilter 背景のみ 2とは別の
  4. CIFilter オブジェクトも なじんでくる ただ60fpsでない
  5. Metal SCNTechnique を使う
  6. Physically Based Rendering (PBR SceneKitにあるやつ) CIFilterでもMetalでもないアプローチ
  7. Physically Based Rendering + ARKit 60fpsで出るし、映り込みもある(ただ設定した写真の映り込みではある)

今後やりたいこととしては、

  1. Lightingの方向と色のリアルタイム化、
  2. PBR+ARKit でリアルタイム画像の使用

Material Components for Android触ってみる / kirimin さん

speakerdeck.com

I/O 2018 でマテリアルデザインが更新された。App bars:bottom, Backdrop, Banners, Extended FAB, Text Field…どうやって実装する?

Material ComponentsというマテリアルデザインのComponentを実装する公式ライブラリがあって、これを使うと良い

準備、mavenのいつもの、compileSdkVersionをandroid-Pに、Material Compoments Themeを使う、リファクタリングメニューからRefactoring to AndroidXを選択。準備完了

TextFieldsは普通のEditTextと同じように使うだけで、TextInputLayoutのstyleを @style/Widget.MaterialComponents.TextInputLayout.OutlineBox 変更するだけで、あたらしい見た目になる

ただ新Componentは見た感じまだあんまり実装されていないっぽい…そのうち用意されるはず

Carthage移行した話 / aboyさん

ビルド、フルビルドで4並列で360秒かかっていた。ビルド時間長いと嫌

CocoaPods使ってて毎回FrameworkのビルドしてたのでCarthageに移行した。CocoaPodsのライブラリが38個あったが、これが16個になり、無事80秒速くなった。

ハマったところとして、CocoaPodsから移行していないライブラリがAlamofireに依存していて、call of deleted methodになってしまっていた。これは全部Carthage経由にして解決した。

忘れないで!mac app!! コマンド編 / Akkey さん

speakerdeck.com

1時間ごとにプロ生ちゃんが時間を教えてくれるmacOSアプリを作っている。

mkdir, cp をどうするかというやりかたを紹介

mkdirする方法 NSHomeDirectory() ホームディレクトリが取れる NSTask()インスタンスを作って、絶対パス/bin/mkdir を呼び出す 注意点としては、Sandboxの有無で取得できるディレクトリが違う

cp する方法 GUIアプリなので、ファイルを選択するのに、ファイルを選択するダイアログみたいなものを出したい これを出すにはNSOpenPanel()のインスタンス作って、設定してbeginのcompletionHandlerで結果受け取る これを引数に、同様の方法でまたNSTask()で /bin/cp を呼び出せばOK これもSandboxの場合は設定変更が必要なので注意

iOSアプリではない領域でSwiftで遊べるのでおすすめ。

感想とか

  • Visual Studio App Centerの話は iOS Test Night でも拝聴したのだけどMS手厚いなーという印象 どうやったら流行るんだろう
  • konifar/gradle-unused-resources-remover-plugin はふつうに今後お世話になりそう
  • Flutter は最近のpotatotipsでも毎回誰か触れているので熱高まっているなーと感じる 自分もちょっと触ってみたけどたいへん良かった
  • 懇親会楽しかった‥

potatotips #50 に参加しました (iOS, Androidブログまとめ)

potatotips #50iOSブログまとめ枠で参加させていただきましたのブログです。

f:id:kumamotone:20180420011750j:plain

会場はWantedlyさん。めっちゃおしゃれ(語彙) すごく見やすくて聞きやすい環境でしたし、持ち時間時間が見やすく表示されていて発表しやすそうでした。

f:id:kumamotone:20180420011818j:plain

50回目ということでスピーカーの方々もはじめて発表したときのこととか振り返ったりされてました。

以下発表内容です。参加枠としては iOSブログまとめ枠でしたがAndroidの発表内容に関してもまとめてみました。間違いや気になるところなどあればご指摘ください。

埋まっていない資料は公開されたのを見つけ次第反映します。

"Hello Flutter"の次におさえたいFlutterのポイントその3 / Kenichi Kambara さん

www.slideshare.net

その2

www.slideshare.net

その1

www.slideshare.net

Flatterの概要、特に今回はUIに焦点を絞った話。

FlatterではDart言語でWidgets Treeというものをガリガリ書いていくことになる。Scaffoldというテンプレートクラスを使って作っていく。ScaffoldにはAppBarとBodyがぶら下がっている。

Columnというのを使うと、AndroidでいうLinear Layout の Verticalみたいなものが実現できる。Columnにまたボタンとかテキストフィールドがぶら下がっている。

Flutter向けのGUIビルダーが Google I/O で発表されることを期待しています!

recyclerview-selection / kgmyshin さん

speakerdeck.com

recyclerview-selectionの概要と、つかいかたについて。

recyclerview-selection とは?

28.0.0 alpha1から導入された、複数選択の機能の。ドラッグして複数選択みたいな機能が簡単に作れますよみたいなライブラリ。マウスなどにも対応しているらしい。

使いかた

Recyclerview, Viewholder, Adapterは一旦ふつうに作る。ただ、stableIdを使うようにする。SelectiontrackerインスタンスSelectionTracker#Builder でつくる。各引数に、Key、使うRecyclerview、StateIdKeyProvider、今どこのアイテムを選択している解決するItemDetailsLookUp、StorageStrategy、必要だったらリスナーを与える。あとはViewに選択状態を反映しておわり。

ブログにもっと詳しく乗ってるよ

inside.dmm.com

サンプルコード

github.com

Yet another simple Logger / ngtk さん

speakerdeck.com

XcodeのConsole log使ってますか?なるべくデバッガーをつかわずに問題解決したい。たとえばログとか。

ただログ機構に不満がある。ロギングのレベルが指定できない。ライブラリの標準出力がコントロールできない。

github.com

ライブラリ色々見たが、Swiftybeaver がオッとなった

:star: 3500 ぐらいで、ログレベルに対応してて良い。一方出力先も指定できる。文字列をコピペできない、有料のプラットフォームとセットになっている、とか概ねいいけど微妙なところもあった。

欲しい機能ぐらいであれば自分で作れるかもということで作ってみた。ざっくり実装紹介。

Glide 4 with Kotlin / hkusu さん

speakerdeck.com

画像ライブラリGlideの使い方とGlide4の機能の話。

hkusuさんのプロジェクトではpicassoがメンテされないのでGlideに乗り換えたという経緯がある。

Transformation。Glide4 では クロップ、角丸は標準で用意されている。また Glide Transformations使うとBlur, BrightnessFilter とか凝ったやつも簡単にできる。Glide4でアニメーションのデフォルトがフェードなしになったことに注意。

Glide Optionではよく使うオプションを定義して再利用できて便利。便利なんだが、Transitionや、サムネイル・リスナーの設定などはできない。これはGlide Typeとして定義できるがGlide Optionに比べると制約がある(複数指定できない、引数指定できない)。

しかし、Kotlinなら拡張関数があるので、GlideRequestとかに生やしてしまえば同じように処理をまとめられる。

Tagged / to4iki さん

speakerdeck.com

Idを型化したい。たとえば Userって型とSubscriptionっていう型があって、それぞれにidがあるのだが、これらは違うもの。なのでStringとかじゃなくて型にしたい。

ほかの例として、 Codable を使う場合は、decoderを実装すればよい。ただ、これいちいち書くのめんどいし、Userの比較するのにEquatableをIdにも実装せんとあかんのかよとなる、

structの各要素のEquatableの実装めんどくさい問題は、Swift4.1のConditional Conformanceで解決した。

github.com

さらに、この機能を使ったTaggedというライブラリがあり、これを使うことでプリミティブな型を簡単に型として扱うことができる。

DiffUtil and ListAdapter / kubode さん

speakerdeck.com

DiffUtil と ListAdapter の紹介。

github.com

DiffUtilでは、2つのListの差分をO(n)で計算できる。これは1000個のリストのうち50個の変更があったとき、Nexus5Xで4.6秒で計算できる速さ。

ListAdapterは、Support Library に 27.1.0で追加された、DiffUtilをつかうRecyclerView.Adapter。デモ。簡単。注意点としては、MutableListと一緒に使ってはならない。

From ObjectMapper to Codable / kobakei さん

speakerdeck.com

APIが返してくるJSONをObjectMapperでやってた部分をCodableにおきかえた。

Codableの基本的な説明。ネストしたJSONのパースの仕方、CodingKeyの話、日付String→Dateに変換など。JSONがつらい形で返ってきても、Decoderを自前実装すればよしなに対応できる。

ちなみにCodableAlamofireというのを使うと、responseDecodableObjectというのがrequestに追加されて、そんまんまCodableの型のオブジェクトを受け取れる。

github.com

Viewのキャプチャを撮ってみる / e10dokup さん

www.slideshare.net

特定のViewだけをキャプチャしたいときどうする?こういうときは、android.R.id.contentでActivity全体をキャプチャできる。これやると通知領域のないスクショが撮れる。

android.R.id.contentで画像としてキャプチャする場合。View#getDrawingCache()でViewのキャッシュを作成してBitmapで取得する(android-ktxならView#toBitmap()でもOK)。これ使うと、子になってるViewもまとめて実行される。注意点としては、使う前にView#setDrawingCacheEnabled(true)しよう。

画像ではなく、PDFとしてキャプチャする場合。PDFのいいところとしては、テキストをテキストとして保存してくれる。PDFDocumentというクラスを使ってキャンバス芸でキャンバスにゴスゴス書いていく感じになるが、たぶんPDFDocumentはこうやって使うものではない…

ほかにもMediaProjection API(API 21〜)を使うという方法がある。MediaProjectionは仮想のディスプレイにミラーリングしてやるという方式(こっちは自前のアプリだけでなくServiceとして起動して任意のアプリのキャプチャ撮ったりできる)。

iOSは自動生成の夢を見るか? / Nonchalant さん

speakerdeck.com

自動生成の前にDIの話。Swinjectを使っている。

github.com

container.register()をゴスゴス書くことになる。動的DIなので参照されるまで気づけなくて、間違うとクラッシュするとかありうる。

github.com

Sorceryは自動生成ツールで、これを使うとボイラープレート自動生成してくれる。Stencilテンプレートというのをテンプレート言語としてつかう。

紹介したコードでは、命名規則を利用したが、Sourceryはあるプロトコルに適合している型だけを抽出するとかできるので、Prefixとかずれても大丈夫なはず。

SourceryにおけるStencilの文法は以下にあります。

github.com

Preferences as a Service / izumin5210 さん

speakerdeck.com

アプリで使用する設定値、どこに保存する問題。結局サーバー側の挙動に影響するものが多いので、Shared PreferenceやRealmなどを使う方法もあるが、結局ローカルだけに保存するという選択肢が取れない場合もある。

しかしアプリごとに毎回同じような設定用のサーバーを立てるのはつらい…なので汎用的に設定値を管理するサービスないわば、Preferences as Serviceをつくった。

また内製なので、外に出したくない情報も使うことができる。またアプリでViewにそのままマップできる形で返すとか、A/Bテスト用の機能などをつけたり、色々便利に使っている。

今更C++でアプリを書く / 5mingame2 さん

www.slideshare.net

専門学校でゲームの作り方を教えたりしている。現在はCinderというのを使ってボードゲームカルカソンヌっぽいアプリを作っている。

github.com

あまり手厚いサポートはないが、学生がはじめて3Dを触るのに丁度よい規模感。UnityやUnrealEngineだと便利過ぎる。公式リファレンスは割りと充実しているが、ネットでググってもほとんど情報がないので、教育的(?)。

OpenGLの薄いラッパーとして使える、便利な点として、OSの違いを吸収してくれる。特にサウンドとか自分でやるとエグいので良い。またUnrealEngineなどと比べて良いところとして、ライブラリの再ビルドでトラブルが少ない。XcodeやVS2017が使えるならC++14が使える。

iOS SDKが使いたい場合は、Objective C++つかえばC++のコードからObjective-C使える。

ゲーム作れるが、手間がかかるのであまりお薦めはできない(編注:おすすめはできないと言いながらも楽しそうだった)。

消費型課金を導入する / morizooo さん

Presentations by morizooo // Speaker Deck

課金方式、消費型課金、非消費型課金、購読型課金がある。今日は消費型課金の話をする。

Play Billing Library。おすすめの習得法、play-billing-codelabさわって感触を掴んでからTrivialDriveV2を使うのが良い。

できること。課金できる端末か調べる、購入情報の取得、商品情報の取得、Google Playの購入画面を出すなど。

課金フロー。クライアントGoogleに→レシートを受け取る→サーバーに対してレシートの検証を行う(このとき購入したユーザー、アイテムの情報も送る)→Googleに検証してもらう→レシートの検証結果をクライアントに投げる→消費リクエストをクライアントからGoogleに送って終わり

複数端末で操作するとか、色々なクラッシュ要因があるがあるので、色々考えつくのはやるとして、フェールセーフになるように気をつけたほうがいい。

キーボードの切り替えをいい感じにしたい / wakwak3125 さん

speakerdeck.com

Facebook Messengerアプリとかで見る絵文字とか表示するキーボードの切り替えをしたい。適当にやったら豪快にViewが動いたのでやり方を考えた。

まずMessengerアプリを参考にした。単純にView構造のdumpを adb shell dumpsys activity top でとってみてひたすら切り替えてみた。そうすると気づいたのだが、特に変わったCustomViewを使っている様子はなかった。キーボードの裏にViewがある雰囲気を掴み、キーボードを閉じる際に高さが変わらなければ、View豪快に動くことがないのではと考えた。

実際にやってみた。toAdjustNothing(), toAdjustResize()を適切に使うようにしたら、キーボードを閉じる際に高さが変わらなくなり、問題が解決した。が無理矢理感があると思っていて、やりかたを募集している。

コードは以下に置いてあります。

github.com

Introducing Izumo / nakajijapan さん

speakerdeck.com

Izumoという、macOS, iOSで動くMarkdownエディタを使ったので紹介。CloudKit + CoreDataを使用してクラウドと同期をとるのと、リアルタイムMarkdownパーサを実装しているのが特徴。

Swiftが発表されたタイミングで発表されたCloudKitだが、なかなか同期処理がつらい。Markdownのパースも正規表現ゴリゴリでつらい。同期もCloudKitというフレームワークを使っているからといって単純に出来るわけではなく、結構やることある。

色々つらいが普段できない体験ができてよかった。

ディープリンクを実装した / Takasy さん

speakerdeck.com

通知から該当ページを起動する、という機能をつくる。

起動している/していない、登録している/登録しないの組み合わせパターンでそれぞれ違うことする。たとえば起動していて登録済みならページを開く、起動していないなら起動画面を見せてからページを開く、未登録で起動中なら何もしない、未登録で起動していないなら起動するだけ、という感じ。

どう実装したかというと、起動画面を透明なActivityにする、条件分岐をして適切な処理をすると言う流れ。

透明にする方法はStyleを設定する(windowsistrunscrentをtrueに)。条件分岐の方は、起動activityにdataをつけて、oncreateでintent.dataにuriが入ってるのでスキームをパースする。

ただホーム画面をスタックに積むというところで詰まって、droid girlsの方に質問とかして解決した。TaskStackBuilderというのを使うとActivityを起動せずにスタックにつめる。FlagにはSINGLE_TOPを設定しておく。

RxSwift, Codable, Moya で API クッキング! / Akkey さん

YoutubeAPIを叩くアプリ。軽い気持ちで技術選定して、RxSwift, Codable, Moya を使ってみた。

github.com

Moyaではenumでエンドポイントを定義して、リクエストごとにcaseを定義する。

MoyaにはTargetTypeというプロトコルがあって、エンドポイントはこれに準拠させて extension で baseURL, path, method, parameters を実装することによって設定する。

RxMoyaを使う場合、注意点としてリクエストを行うAPIクラスは、シングルトンでProviderが開放されないようにする必要がある(結果をSubscribeできなくなるため)。MultiTargetというのを使うと、Providerごとに型が違っても共通で使えるようになる。

webviewが辛かった話 / aboy さん

WebViewがつらかったという話。「Webサービスのアプリ版がほしいな〜」という案件を任された。

Web版できることはやりたい、ログイン状態は保持したい。ということで、WebViewでやることになった。

しかし案の定、WebViewの謎の挙動に悩まされ大変な目に…

なぜこんなことになったのか、ヘッダーリクエストまわりをいじったせいで、戻るの機能が使えず自前実装になって実装が複雑になっていった。またもともとページ数がかなりあるWebサービスなので、動作を担保する範囲がめちゃくちゃ広かった…

WebViewは安易につかうとつらいです。ちゃんとWebViewを使うべきなのかよく考えましょう。

感想とか

github.com

  • Taggedは早速Swift4.1の機能を活かしていて面白いライブラリだなと思いました。

  • iOSはいい感じのデファクトっぽいロギングライブラリが出て来ると良いですね…Timberやlogger的な…(あるのかな?)みんな各々実装してそう

  • AlamofireとRxSwiftは個人的に使っているのですが、RxMoyaと組み合わせるとすごく良い感じになりそうなので参考になりました。

  • Webサービスのアプリ版がほしいな〜」みたいな案件、今後遭遇するかわかりませんが、恐ろしそうなので気をつけようと思いました…

potatotips #49 に参加しました (iOS, Androidブログまとめ)

potatotips #49iOSブログまとめ枠で参加させていただきましたのブログです。

メルカリさんの会場。

f:id:kumamotone:20180313202426j:plain

f:id:kumamotone:20180313202404j:plain

大変良さ。

f:id:kumamotone:20180314011310j:plain

f:id:kumamotone:20180314011318j:plain

成城石井の高めのポテチとヘルシーピンチョス。良さ良さ。

以下発表内容です。iOSブログまとめ枠でしたが今回もAndroidの発表内容に関してもまとめてみました。間違いや気になるところなどあればご指摘ください。

埋まっていない資料は公開されたのを見つけ次第反映します。

XCTestを目的別に分けるすすめ / gaopin さん

speakerdeck.com

数ヶ月前、チームにジョインしてあることに気づく。自動テストコケとるやん。

gaopinさん「自動テストこけてるよ」

チームの人「問題ないw」

gaopinさんのプロダクトは、膨大で複雑なログの絡むプロダクトで、スプリントごとにテストを回していて、スプリント途中はテスト通らなくてもしょうがないみたいな感じになってた。

でもこれテストターゲットを分割すれば良いだけの話。

方法も簡単で、

  1. (プロジェクトの↙にある+)ターゲットを追加 iOS Unit Testing Bundle を追加

  2. 分割したいテストのファイルのメンバーシップを変更

みたいな感じ。これで個別に実行できるようになった!

おすすめの分割タイミングは以下。

  • 実行タイミングが違う
  • 実行する範囲が違う
  • 別チームで作業している(これは微妙かも)

OK google, プロジェクトのbuildして」 / satsukies さん

speakerdeck.com

前回のpotatotipsの Alexa、APKを配布して // Speaker Deck が面白かったのでやってみた。

流れ。我々「プロジェクトHogeをビルドして」→GoogleHome「わかりました」→GAS等使って「プロジェクトHoge」に対応するBitrise起動→Bitriseでビルドしてapk配布。対話を通じてプロジェクトIDを聞き出す。

DialogFlowで、Agentの作成して、Entityの登録して、Intentの登録する。Entityの取り出しはTraining Phrasesにユーザーの発言を入力するだけ。するといい感じにパラメータを学習してくれる。最後にResponse定義する。Default Fallback Intent(うまくいかなかったときの反応)もここで定義。

その先の内容は飛ばしてActions on GoogleのSimulator を使ったデモ。

ExoPlayerで音遊び / daasuu さん

予習。ExoPlayerとは

Google の動画ライブラリ。

github.com

shunirr.hatenablog.jp

ExoPlayer とは:

従来の MediaPlayer (Stagefright / NuPlayer) は C や C++ で実装され、かつ実装は Android フレームワークに組み込まれているので、 MediaPlayer 内部で不具合があったときに修正や、 MediaPlayer そのものを修正して新たなフォーマットやプロトコルに対応させることをアプリ開発者が自由に行なえず、端末や OS のアップデートが必要でした。

ExoPlayer は Google が開発している Android 向けの新しいメディアプレイヤーで、全て Java で実装されており、またアプリケーションに組み込んで利用するライブラリの形式で配布されています。

これにより従来の MediaPlayer で不可能だった、アプリ開発者によるプレイヤーの拡張や修正が可能になっています。

内容

Presentations by Masayuki Suda // Speaker Deck

Androidでの音再生の方法おさらい。MediaPlayerはBGM等の長い音の再生に使える。SoundPoolは5秒未満なら良い。AudioTrackはバイナリ直なので難易度が高いが、自由度は高い。

ExoPlayerというライブラリがある、これは動画のライブラリ 動画再生だけでなく音の再生にも使える。

最近では音程や倍速にも対応できるようになってきた。ピッチではなくスピード、音程だけでも設定可能。すごい。

TD PSLOLAアルゴリズムを使っている。これは音のスペクトルをある程度保ったままピッチやテンポを保ったまま上げれる。

具体的には、以下のような感じでやってる。

  1. ピッチに対応した波形の1周期をみつける
  2. 周期を切り出す
  3. 切り出した周期を使って音声を再合成

これをやっている部分だが、ExoPlayerでSonicで検索すると良い。ちなみに48k→44.1kのリサンプリングなどもできる。

たった2行で本格アプリ!?挫折しないSwift勉強会の裏側 / AkioItaya さん

iOSアプリの作り方を教えたりされているAkioItaya さん。

github.com

教え方の一例を紹介。キャラクターと一緒に記念撮影を行えるシンプルなカメラアプリ↑をcloneしてもらう。2行書くだけで完成、という状態にしてある。

なぜ2行の実装で終了するのかというと、2行追加するViewControllerの継承元のクラスやextensionに実装が隠蔽されていて、それらを種明かしをしながら動作を理解してもらっている。

とりあえずちょっと何か書いて動く状態にしてわくわく感を得た後、逆順に説明することによって挫折しない工夫をしている。

shared element基本のき 〜パターンで見るshared element〜 / e10dokup さん

予習。shared element とは

developer.android.com

f:id:kumamotone:20180313180730p:plain

Shared Elements 遷移は、2 つのアクティビティで共有されているビューが、各アクティビティの間でどのように遷移するかを決定します。 たとえば、2 つのアクティビティで同じ画像を異なる位置とサイズで使用している場合、changeImageTransform 共有要素の遷移によって、2 つのアクティビティの間でスムーズに画像が変換されスケーリングされます。

re-engines.com

Airbnbとかで使われてるUIらしい。ぽよんって遷移するやつ。API 21から使える。

内容

speakerdeck.com

Shared Element Transitionはガン遷移前後で共通になっているviewをアニメーションさせるもの。Google Play Storeのアプリリスト->詳細とか。

Shared Elements viewにtransitionNameを着ける

Activity-Activityの場合、Fragment-Fragmentの場合、RecyclerView-Activityの場合、RecyclerView-ViewPagerの場合をそれぞれ説明。

RecyclerView-ViewPagerパターンめっちゃめんどくさい。

あとShared Element Transitionしないほうがよさそうなときもあって、遷移前後でshared element対象のViewのVisibilityが保証できないとき、遷移前後で保持するリストの内容が違うときなどがある。

リポジトリ

github.com

App Store 予約注文を使ってみた / toshinarin さん

App Store、予約注文としてリリースができる。24時間以内に(時間は指定できない)自動的にユーザーの端末にダウンロードされる。

予約注文数が見れてPR・マーケティング的に良いし、利用可能になったら自動的にダウンロードされてメールとPushがくるのでユーザビリティ的にも良い。

実際の設定の仕方は簡単で、価格及び配信状況のバージョンのリリースでできる。

注意点としてはアプリを使い始める時間を完全にはコントロールできない。

ちなみにアプリ自転車が必要で審査できないので、動画で撮影して App Reviewに関する情報>メモに動画を添付とした。

動画編集についてだが、iPhoneで撮影、iMovieで編集すればPinPとかもできるので良い。

Swiftバグレポートレポート / kazuhiro4949 さん

speakerdeck.com

bugs.swift.orgからXcode 9.2 で再現できるバグをピックアップ!

SR-7090 Codable に関するバグ

  1. クラスAがCodableを実装している
  2. クラスBがAを継承している
  3. Bを初期化orデコードして、プロパティにアクセスするとランタイムエラー

SR-7102 パフォーマンスに関するバグ

Swiftでは複雑な式を書くとコンパイルが中断されることがあるのだが、似たような式を書いても中断されるとき、されないときがある。

SR-7115, SR-7120 キャプチャリストに関するバグ

SR-7115。クロージャのキャプチャリスト内で??を使用してコンパイルすると確実にセグフォになる。

SR-7120。キャプチャリストがついていないクロージャ内でrethrowするとコンパイラエラーにならないが、ついているとエラーになる。

バグレポート眺めると意外と簡単に発生してしまうバグを知れて楽しい!!

ReactiveSwiftに習うCollectionの最適化とパフォーマンスチューニングパターン / ryo_aoyama さん

speakerdeck.com

ReactiveSwiftにBagというのがあって、Signal(Observableっぽいやつ?)をKeyで管理している(たぶん)なのだが、これがどういう高速化をやっているかという話。

1。ContiguousArrayを使う。classか@objcのときにメモリの連続した領域に格納し、イテレーションを高速化できる

2。最適化済みのstdlibをそのまま利用することにより自前実装よりも高速化出来る場合がある

3。デフォルトで実装されるIndexingIterator内部で関数呼び出しにコストがかかるため

4。あとから追加されたもののほうがremove(for: )されやすいという考えで逆順に探索。

実験。add, iteration, remove を10,000件に対してやったら200倍高速化していることを確かめた。

配列はパフォーマンスチューニングしやすいので重い場合はおすすめ。

“Hello Flutter”の次におさえたいFlutterのポイント / Kenichi Kambara さん

練習に作ったアプリの紹介と、Hello Flutterの次にするとよさそうなこと。

Flutter 書くの、Android Studio使うと便利。SDK入れる。flutter doctorでチェックできる。Flutter用のプラグイン導入で簡単。これでDartも入る。起動時のダイアログでStart a new Flutter projectできる。良い。

Perform hot reload on save で Save 時に Hot reload も可能。View 例で出てきたアプリだと、ScaffoldにAppBar, body, FAB がぶら下がっている感じ。

OS別テーマ切り替えなどもできる。DartでViewを書くっていうのがちょっとつらいかもだが、ハマると良さそう。

独自Documentクラス / 村上幸雄 さん

fr.slideshare.net

MVC、よく批判される古典的なMVCと、AppleCocoa versionとして提唱しているViewとModelが干渉しないタイプのMVCがある。

Macアプリの場合NSViewとdataがNSDocumentとNSViewControllerを介して連携することになりそう。Document(Controller)部分に使えるものとしてiOS5から使えるUIDocumentクラスというのもあるが少々オーバースペックなので、Documentを独自実装したときの反省点などを紹介。

Spannable芸〜郵便番号編〜 / HiroYUKI Seto さん

予習。Spannableとは

weide-dev.blogspot.jp

Spannable はテキストをマークアップするためのインターフェースです

CharacterStyleなどのクラスを使って文字列の一部を 下線を引いたり、下付き文字にしたり、 上付き文字にしたり、URLを付けたり... と様々なことができます

内容

speakerdeck.com

最高の郵便番号入力欄を作りたい。

  • 3桁目と4桁目の間にハイフンを表示させたい
  • 3桁目を打ったらハイフンの後にカーソル移動
  • シームレスに移動。7桁ペーストしたらペーストされるし4桁目で文字削除したら左に移動。カーソル移動も。

EditTextでは解決しきれない。それでSpannableを使う。これは文字列のデコレーションのinterfaceで、未確定文字列の色などもSpan。ReplacementSpan、これはTextViewの文字列を置換するSpanで、独自絵文字なんかはこれで作られている。

ReplacementSpan で気合入れつつ実装 サンプル↓

github.com

UITableViewControllerの利点を最大限に活かす使い方 - コードでAutoLayoutを記述する場合 - / masashi-air さん

speakerdeck.com

ContainerViewを使えばUITableViewControllerの利点を最大限に活かしてレイアウトできる。

UITableViewController、UIViewControllerにtableView貼り付けるに比べて色々利点があって、

公式ドキュメントに書いてある

  1. tableViewプロパティに非オプショナルでアクセス可能
  2. delegate, dataSourceがデフォルトで設定済み
  3. clearsSelectionOnViewWillAppear
  4. 表示時にテーブルのスクロールインジケータを点滅
  5. setEditing(_: animated :)

のほかに、なぜ書いてないのかわからないがキーボードの高さを考慮して入力範囲を隠さないようにスクロールしてくれたりする。

ただ、難点あって、画面下にView置きたかったりしてaddSubViewしたりすると表示おかしくなったりする。

が、ContainerView使うとうまくいく。iOS10以前だとtableViewのInsetに設定が必要だが、ContainerViewを持っているVCにif #available(iOS 11.0, *) { } else { /* ほげほげ */ } とかやっておけば後々コード整理しやすい。

サンプルです↓

github.com

try! Flutter / Rui Kowase さん

docs.google.com

Flutter 書くの、Android Studio使うと便利。SDK入れる。flutter doctorでチェックできる。Flutter用のプラグイン導入で簡単。ビルド速くて良い。Hot Reload良い。オフィシャルドキュメントが充実している。

サンプルアプリの紹介。Scaffoldというのが使える。async/await使える。

github.com

おまけ。Flutterはときめきますという意味らしい。エラーのスクリーンのカラーコードが #7C160E とかで比較的心温まる。

Introduction to LLVMSwift / kitasuke さん

予習。LLVMSwiftとは

github.com

LLVMSwift is a pure Swift interface to the LLVM API and its associated libraries. It provides native, easy-to-use components to make compiler development fun.

内容

持ち帰って欲しいtips

LLVMSwiftの紹介。LLVMSwiftはLLVM C APIのSwiftのラッパー。Swiftコンパイラーのコミッターが2人居て主にその人達が書いてる。

サンプルのシンプルなプログラムとその出力のLLVM IR見てみると、まぁただのSwiftのラッパーだな〜という感じ。わざわざCのコード読んで勉強するより分かりやすいはず。

Cで使えばいいじゃんってなるけど本人達も名言してるかどうかしらんがLLVM、Swiftで書いたぜっていうそういう勢いが大事。

README.md に書いてあるIntroductionの説明。

界隈でSwiftコンパイラ流行っていて、silとかASTとかLLVMコンパイラとかいろんな層ある。でこういうのあると勉強に良さそうなので紹介しました。

感想とか

iOSでShared Element Transitionっぽいやつ

もっと気軽にUITableViewController使いてぇよ

Flutterさん我々を救ってください

HammerspoonでどのウィンドウでもEmacs風キーバインドを使う

経緯

macOS Sierra になってからKarabinerが使えなくなって以来(自分は2017年4月頃〜)、Hammerspoon を使ってています。

現在ではSierra以上でも動くKarabiner-Elementsの安定版が出ているので使ってみたのですが、以下の2点が自力で克服できておらず、まだちょっとしんどいのでまたHammerspoonに戻ってきました(誰かがなんとかしてそうだけど…)。

  • Office(Outlook) で何故かバインド(Ctrl+A, Ctrl+E)が効かなくなる
  • Ctrl+A/E の移動は、単なる行頭行末移動ではなくMove to beginning of text (インデントを考慮して行頭) になってほしい

というわけでほぼほぼ1年使ってある程度手に馴染んできたのと、Karabiner-Elementsの安定版が出た現在でも Hammerspoon で設定を書きたい、書きたいがうまくいっていないという人もいるんではないかと思い、一旦軽くまとめてみることにしました。

HammerSpoon

www.hammerspoon.org

Hammerspoon はキーリマップツールというよりかは自動化ツールと謳っていて、リマップ以外にウィンドウサイズの変更や移動、WiFiやUSBデバイスの監視なんかもできるみたいみたいです。

設定ファイルはLuaという言語で書きます。ある程度馴染みのあるPythonで設定が書けるkeyhacというソフトもあるので、最初はLua…うぐぐ…となったのですが簡単な範囲なら思ったより全然困ったことが起こらず直感的に書くことができました。

設定ファイル

とりあえず設定ファイルを晒します。

--
-- Hammerspoon用 KeyRemap 設定
--

local function keyCode(key, modifiers)
   modifiers = modifiers or {}
   return function()
      hs.eventtap.event.newKeyEvent(modifiers, string.lower(key), true):post()
      hs.timer.usleep(1000)
      hs.eventtap.event.newKeyEvent(modifiers, string.lower(key), false):post()
   end
end

local function remapKey(modifiers, key, keyCode)
   hs.hotkey.bind(modifiers, key, keyCode, nil, keyCode)
end

local function disableAllHotkeys()
   for k, v in pairs(hs.hotkey.getHotkeys()) do
      v['_hk']:disable()
   end
end

local function enableAllHotkeys()
   for k, v in pairs(hs.hotkey.getHotkeys()) do
      v['_hk']:enable()
   end
end

local function handleGlobalAppEvent(name, event, app)
   if event == hs.application.watcher.activated then
      -- hs.alert.show(name)
      if name ~= "iTerm2" then
         enableAllHotkeys()
      else
         disableAllHotkeys()
      end
   end
end

appsWatcher = hs.application.watcher.new(handleGlobalAppEvent)
appsWatcher:start()

--
-- ここから KeyRemap 設定
--

-- カーソル移動
-- 現状 hs.hotkey.bind の挙動が怪しいので getFlags+getKeyCode を使うといい
hs.eventtap.new({hs.eventtap.event.types.keyDown}, function(e)
  -- Ctrl + Shift + FBNP(ctrl単体のものよりより先に書く必要がある)
  if e:getFlags().ctrl and e:getFlags().shift then
    if e:getKeyCode() == 35 then
      hs.eventtap.event.newKeyEvent({"shift"}, "up", true):post(); return true;
    elseif e:getKeyCode() == 11 then
      hs.eventtap.event.newKeyEvent({"shift"}, "left", true):post(); return true;
    elseif e:getKeyCode() == 45 then
      hs.eventtap.event.newKeyEvent({"shift"}, "down", true):post(); return true;
    elseif e:getKeyCode() == 3 then
      hs.eventtap.event.newKeyEvent({"shift"}, "right", true):post(); return true;
    elseif e:getKeyCode() == 6 then
      hs.eventtap.event.newKeyEvent({'shift','cmd'}, 'z', true):post(); return true;
    end
  end

  -- Ctrl + FBNP
  if e:getFlags().ctrl then
    -- log の吐き方
    -- local log = hs.logger.new('mymodule','debug')
    -- log.i(e:getKeyCode())
    if e:getKeyCode() == 35 then
      hs.eventtap.event.newKeyEvent({}, 'up', true):post(); return true;
    elseif e:getKeyCode() == 11 then
      hs.eventtap.event.newKeyEvent({}, 'left', true):post(); return true;
    elseif e:getKeyCode() == 45 then
      hs.eventtap.event.newKeyEvent({}, 'down', true):post(); return true;
    elseif e:getKeyCode() == 3 then
      hs.eventtap.event.newKeyEvent({}, 'right', true):post(); return true;
    -- PCライクなバインディング、たとえば
    -- ctrl + W を cmd + W にするのも hs.hotkey.bind だと何故か出来ないので
    -- こっちの方法を使っている
    -- elseif e:getKeyCode() == 6 then
    --   hs.eventtap.event.newKeyEvent({'cmd'}, 'z', true):post(); return true;
    -- elseif e:getKeyCode() == 7 then
    --   hs.eventtap.event.newKeyEvent({'cmd'}, 'x', true):post(); return true;
    -- elseif e:getKeyCode() == 8 then
    --   hs.eventtap.event.newKeyEvent({'cmd'}, 'c', true):post(); return true;
    -- elseif e:getKeyCode() == 9 then
    --   hs.eventtap.event.newKeyEvent({'cmd'}, 'v', true):post(); return true;
    -- elseif e:getKeyCode() == 13 then
    --   hs.eventtap.event.newKeyEvent({'cmd'}, 'w', true):post(); return true;
    -- elseif e:getKeyCode() == 46 then
      -- hs.eventtap.event.newKeyEvent({}, 'return', true):post(); return true;
      -- hs.eventtap.keyStroke({}, 'return');
    end
  end

  return false
end):start()

-- 行頭行末移動
-- home/end は 行頭ではなく、Move to beginning of text (インデントを考慮して行頭) になってほしい
remapKey({"ctrl"}, "a", keyCode("left", {"cmd"}))
remapKey({"ctrl"}, "e", keyCode("right", {"cmd"}))

remapKey({"alt"}, "b", keyCode("left", {"alt"}))
remapKey({"alt"}, "f", keyCode("right", {"alt"}))
remapKey({"alt"}, "n", keyCode("down", {"alt"}))
remapKey({"alt"}, "p", keyCode("up", {"alt"}))

remapKey({"alt"}, "h", keyCode('delete', {"alt"}))
local function deleteWordForward()
  keyCode('right', {'shift', 'alt'})()
  keyCode('delete')()
end
remapKey({'alt'}, 'd', deleteWordForward)

-- Return
remapKey({'ctrl'}, 'm', keyCode('return'))

-- Delete
-- Ctrl+H を文字編集以外(ブラウザバック)でも使いたいため
remapKey({'ctrl'}, 'h', keyCode('delete'))

-- Ctrl+K は OS 標準のものを使用
-- Office だと効かない 悔しい

-- ページスクロール
remapKey({'ctrl'}, 'v', keyCode('pagedown'))
remapKey({'alt'}, 'v', keyCode('pageup'))

-- Esc
remapKey({'ctrl'}, 'g', keyCode('escape'))

--
-- 参考
--

-- 【テンプレ】
-- Karabiner 使えない対策: Hammerspoon で macOS の修飾キーつきホットキーのキーリマップを実現する - Qiita
-- http://qiita.com/naoya@github/items/81027083aeb70b309c14

-- 【行頭、行末移動】
-- Sierra+Hammerspoonでキーバインドを設定する - たまめも(tech)
-- http://tamamemo.hatenablog.com/entry/2017/01/30/183650

-- 【hotkey.bind の代替】
-- 5ch
-- https://potato.5ch.net/test/read.cgi/mac/1485327943/#217

-- 【困った時】
-- Hammerspoon docs
-- http://www.hammerspoon.org/docs/index.html

-- 【Ctrl+K (使わなかった)】
-- http://qiita.com/swdyh/items/04f7da8c1209a067add5
-- local function killLine()
--   keyCode('e', {'shift', 'ctrl'})()
--   keyCode('x', {'cmd'})()
-- end
-- remapKey({'ctrl'}, 'k', killLine)

やりたいこと

Ctrl + X 始動のキーバインド等は使っていないので基本的な部分をEmacsっぽくしています。以前Windows用にKeyhacの設定ファイルを書いてた時にはもっとゴチャゴチャ色々書いていたのですが、割りと削ぎ落とされてこのくらいになりました。

Ctrl + FBNP: →←↓↑

Emacs風移動。あんまり合理的とも思わないキーマッピングですが、身体に馴染んでしまっているので墓場まで持っていくしかない。テキストエリアだけでなくFinderやChromeなどでも使いたいので完全にリマップしてしまいたいキーです。

Shiftキーを押すと範囲を選択したいし、Altキーを押すと単語ジャンプにしたいです。単語ジャンプはプログラミングのときなど、ASCII文字ばっかり出てくる時は大抵活躍しますし、JetBrainsのエディタならAlt+↑↓はかなり素早く範囲指定できるので協力です。

2017年4月時点では hs.hotkey.bind の挙動が怪しいらしく、カーソル長押し移動が効かなくなるので下記を参考に getFlags+getKeyCode で設定するようにしました。がもしかするとAltキーのほうが今元気に動いているのでこんなに回りくどい方法を取る必要ないかも‥

【Karabiner】キーリマップ・カスタマイズ総合 for Mac【英かな】 [無断転載禁止]©2ch.net

Ctrl + A/E: cmd + ←→

Ctrl + A/E は 行頭行末ではなく、Move to beginning of text (インデントを考慮して行頭) になってほしい(未設定の状態だとXcodeでカーソルが完全に左に行ってしまいつらい気持ちになる)のでcmd + ←→にリマップしました。

JetBrainsのエディタとかだとならないのでXcode使わない人はわざわざマッピングする必要無いかもです。

Ctrl + H: BackSpace, Ctrl + D: Delete

他のCtrl + Hは他のショートカットキーに負けて発動しなくなることがあるし、ブラウザの戻るキーとしても使いたい(ChromeのGo Back With Backspaceというエクステンションを使っています)ので delete にリマップしたいです。

Ctrl+D に関してはOS標準のでほしい挙動になるのでリマップしていないです。他のキーはたいてい大丈夫なのですが、JetBrainsのエディタだとこのマッピングが大体コンフリクトするのでエディタ側のリマップ設定を削除してます。

Ctrl + M: Enter

Enterは遠い(JIS配列だとことさら遠い)のでリマップしておきたいです。

Ctrl +G: Esc

Esc は遠いのでリマップしておきたいです。

Ctrl + V / Alt + V: PageUp / PageDown

このリマップは設定してはいるもののちょっと使いづらくって、表示領域の移動はしてもカーソル移動をしてくれないときがあり、そういうときはトラックパッドに手を伸ばしたほうが速いという感じになります。

Ctrl + Z/X/C: cmd+ Z/X/C

これは最近使ってないです。LinuxやPCのときの癖でCtrl+Z/X/C/Vを押してしまいがちだったので設定していましたが、すっかりMacに慣れて最近は素直にcmdキーを押すようになりました。

困ってるとこ

起動してしばらく経つと Finder などで Ctrl + FBNP が効かなくなるときがある

Reloadするとなおります。たまに起こる。

Chrome の検索バーで Ctrl+N すると検索してほしいが、Chromeに Ctrl+N のショートカットが設定されていて変なURLに飛ぶ

Firefoxだと起きないです。説明が難しいのですが、Chrome はCtrl+Nがホスト名を補完してくようとするキーバインドみたいで、これに負けてしまいます(Karabinerだと起きない)。たとえば hogehoge → Ctrl + N するとhogehoge.com に遷移してしまい、しょんぼりします。

Ctrl+K が Outlookで効かない

local function killLine()
    keyCode('e', {'shift', 'ctrl'})()
    keyCode('x', {'cmd'})()
  end
remapKey({'ctrl'}, 'k', killLine)

Ctrl+Kが効かなくなる場面があって、たとえばお仕事でよく使うOutlookだと効かなくなります。

killLine(Ctrl-K一発でその行を消して内容をクリップボードに入れる)のは上記のような方法で実現できるのですが、自分の欲しい挙動であるmac OSの標準の挙動とちょっと違います。

以下の挙動になるキーマップが思いつけば設定できそうです。

  • カーソル位置から右側を削除
  • カーソル位置が右端ならその位置の改行を削除
  • クリップボードは汚してほしくない

ただ行まるまる1行コピー、削除、貼り付けのショートカットは

まとめ

Hammerspoonの設定ファイルの紹介と、なんでこういう設定にしているのかという理由などをまとめてみました。

個人的には国産 Karabiner-Elements にとても期待してます(少額ですが寄付させていだきました)。Office で Ctrl+A/E が効かなくなる問題はぜひご存知な方いらっしゃったら対策を教えてください><

若い頃(学生の頃)は「設定ファイルをゴチャゴチャいじるのは時間の無駄、デフォルトが一番じゃよ」という達観おじさん達を少し軽蔑していたのですが、自分も段々気持ちがわかってくるようになり、こういう設定ファイルをいつまで書いているかはわかりませんが、まだ多少、老いに抗っていきたいと感じてます。

potatotips #48 に参加しました (iOS, Androidブログまとめ)

potatotips #48iOSブログまとめ枠で参加させていただきましたのブログです。

Rettyさんの会場。広いし綺麗

f:id:kumamotone:20180222214744j:plain

今回は5分発表+1分質疑応答スタイルでした。最近はそこそこずっと参加しているのですがはじめて見た。

以下発表内容です。iOSブログまとめ枠でしたが今回はAndroidの発表内容に関してもまとめてみました。間違いや気になるところなどあればご指摘ください。埋まっていない資料は公開されたのを見つけ次第反映します。

テスト実行時に不要な初期化コードを実行しないようにする / kNagadou さん

speakerdeck.com

アプリ起動時に初期データを構築することがある。固有の環境変数や外部SDKのセットアップなど‥

初期化処理はAppテスト時はAppDelegateの処理を実行しないようにしたい。ほかにも問題あって、Viewのインスタンスは不要だが、デフォルトだと、Unitテスト時もUIがロードされる。また、テスト用の初期化処理は別のところに分けたい。

これらを解決するにはまずmain関数的なところでテストかどうかを判定する、その後テストならTestAppDelegateとかを実行して、Main Interfaceのロードはプロダクション用のAppdelegateで処理するようにすればよさそう。

main関数的なところでという部分に関しては、実はmain.swiftが暗黙的に呼ばれていて、main.swiftをプロジェクトに追加すれば上書きできて初期化処理書ける。

Android Instant Apps対応した話 / take_e10 さん

www.slideshare.net

Instant Apps対応した。Instant Appsには制限ある。今現状だと使えない機能、そもそも非サポートな機能。Module<4MB必須とか‥

特に4MB制限がキツイ。Instant Apps対応はほぼほぼこの作業となる。Module分割で4MBを目指す。APK Analyzerでサイズ見れるが、4MB超えるとアップロードした時点でエラーになる。

やったことの中で効いたのはやはり画像。WebPにしたりVectorDrawableにしたり。

ちなみにic_launcher.png (ドロイドくん)のアイコン、いつのまにか入っていて消せなかった 18KBもあってつらい‥

Q. 同じ名前のめちゃくちゃ小さいファイルで置き換えるというのはいかがか?

  1. やったと思うのだがなんか無理だった

Androidチームにコンバートされてから半年、いかにしてAndroidエンジニアになったか / niba1122 さん

Android開発を学ぶためにやったこと。最初1ヶ月はUdacityのeラーニングと、赤べこ本やった。

UdacityはAndroid Basics: UserInterfaceというのと、Developing Android Appsというコースをやった。面白かったのは Android Visualizer というのがあって、ブラウザでXML書ける。

Udacityは独学で網羅的に学べて良いが、英語なのでちょっと大変。その後は実践で学ぶ形式となったが、学ぶことが多くてよかった。Udacityと赤べこ本おすすめ。

Q. Udacityいくら?

  1. 無料です

Q.サンプルのバージョンとかは?

  1. 古いこともあるが大きな問題はなかった 言語はJava

初めてのXcode Behavior / TachibanaKaoru さん

speakerdeck.com

Xcode Source Code ExtensionはWWDC2016で紹介された。

公式だぜ!という感じで盛り上がっていたが、蓋を開けてみれば配布、作成、デバッグが大変、動作にかなり制限がある…過去の非公式プラグインでできていたことが出来ない…

一方、Xcode Behaviorというのがある、Xcodeのmenuから使える。太古の昔からある機能。Xcodeから独立していて、スクリプト走らせれる。

Source Code Extensionとの比較。

Source Code Extension Xcode Behavior
Xcodeで今開いているファイルの中身のみを変更できる。 スクリプトでできることはなんでもできる。
Xcodeで開いているファイルの中身のみ取得できる。 起動するときに環境変数が渡せるので、今Xcodeで開いているファイルがわかる。
作成、配布、変更つらい 配布、自分で書いたスクリプトを自己責任で使うスキームで、作成も配布も変更も楽。
GUI表示できない GUI表示できる。AppKitも可。
Xcodeコンパイル言語のみ スクリプトならなんでもOK。もちろんSwiftも可。

実例。

Apple公式のサンプルコード、たとえば以下のページのxcodeprojを開くと、

developer.apple.com

f:id:kumamotone:20180223000529p:plain

マークダウンが表示されている。

f:id:kumamotone:20180223000547p:plain

しかもView in Sourceって書いてあるリンクを踏むとソースファイルに飛べる。どうやらXcodeのソースコメントに- Tag:を入れると、マークダウンファイルなどからソースコードへのリンクが簡単に作れるらしい。

これを自前のプロジェクトでやってみようとすると…

f:id:kumamotone:20180223000801p:plain

f:id:kumamotone:20180223000815p:plain

f:id:kumamotone:20180223000843p:plain

んん…

さっき見たのと違う…となる

ふつうにやると、Xcodeではそもそもマークダウンはレンダリングされず、生のマークダウンがエディタで表示されてしまうもよう。

調べてみるとどうやら、プロジェクトファイルのなかに特定のplistファイルが置かれていればマークダウンをレンダリングしてくれるようになるもよう。

www.toyship.org

でこれを自前で毎回置くのはめんどくさいので、以下のようなスクリプトを書いて Xcode Behavior でやってしまえば便利。

gist.github.com

Xcode Behavior便利。太古の昔から使える技だが、今こそ見直されるべき。

リリースを自動化した話 / TakuSemba さん

speakerdeck.com

リリース、Sembaさんのチームはapkをアルファとして公開、apkをproductionに上げる、githubでrelease noteを書く、というフローにしてる。

apkをアルファとして公開する部分とリリースノートを書く部分を自動化した。

apkをアルファとして公開する部分。gradle-play-publisherというのを使った。gradleにメールアドレスとか書けば使えるようになって、色々設定もできる。

./gradlew tasks --all するとリストが見れる。bootstrapReleasePlayResourcesは現在公開しているapkの情報をとってこれる。これを編集してpublishListingReleaseする。whatnewを編集してpublishApkReleaseする。

リリースノートを書く部分。GithubAPI叩いてCIに組み込めば良い。リリースのタグがプッシュされると、CIが走るようになっている。

Heckelの差分アルゴリズムについて / YuyaHorita さん

a,b c,d e と a,c,e,f を定義 すると差分は直感的に b,d,f となる。これを噛み砕くと、いくつかのコマンドの塊とみなせて、差分アルゴリズムはこれを実装したものといえる。

差分検知、iOSならDiffer, Dwifft, Androidなら DiffUtil などのライブラリがある。 アルゴリズムとしては Myers, Heckel などがあるが、今日はHeckelについて説明。

アルゴリズムの説明。シンボルテーブルを一つ用意して、新しい配列OからNの配列の差分を取ることを考える。配列O,Nの各要素をKeyとして辞書型のシンボルテーブルに登録。Valueには配列O, N内での数、O内でのindexを保存しておく。

次に自分の分身を自分自身以外を参照させて生成。配列O,Nの各要素を1対1対応した配列ON, NAを用意し、1対1対応している要素への参照を保持し、参照先はSymbolTable もしくは もう一方の配列。

これを配列Nにもやってく。相手側の配列に要素があるならindexを変えるMoveでOK、シンボルテーブルしか参照できないなら古い配列ならDelete、新しい配列ならInsertとなる。

これを使うとO(N)で計算が可能。Myers, Wuに関してもGithubに上げるつもりなのでよろしく。

Contact AppっぽいSticky Headerをつくる / e10dokup さん

speakerdeck.com

Contact AppやDroid Kaigiとかで見る名前一覧のアレつくる。

RecyclerView.ItemDecoration。RecyclerViewのアイテムに対して装飾するabstract class。getItemOffsets, onDraw, onDrawOverの 3つのメソッドをoverrideしてつくる。描画はcanvas.drawText()でやる。

サンプルはこちらから。

github.com

Metal Acceleratedかどうかを調べる方法 / shu223 さん

speakerdeck.com

WWDC2017で出た図で、UIKitやCore Animationも低レイヤでMetalを使っている(Metal Acceleratedされている)ことが明らかになった。

OpenGLiOSでは今はMetalの上に実装されているとAppleの人がWWDCのラボで言ってたけど公式情報はない、が裏が取れない。

裏が取りたい‥なんで取りたいかというと、最適化されていることがわかるし、自分の最適化手法が適切かどうかの判断材料になるし、低レイヤに踏み込んで自前実装するかどうかの判断材料にもなる。

試したこと。まずはGPU Reportだが、Metalを明示的に使用していないと、XcodeGPU Reportは出てこない。そこでInstruments。Metal System Traceというのを使うと、明示的に使ってなくてもわかる。ざっくりした見方としては、上から順に実行されていて、ディスプレイに描画されるまでの流れがわかる。

APIのデータのマッピングを約18倍速くした話 / magiepooh さん

画面遷移遅いなーとなって調べたら、SO-04Gとか古い端末とOSだと最悪20秒ぐらい掛かることが分かった…

ちなみにJSONが1MBあって、Kotlin+Moshiでパースしてた。

やっていき。まず対策その1、Moshi はリフレクションを用いているため、コストが高い。Kotshiを使うと20sec->12secになった。

対策その2、オブジェクト生成が多すぎるのではとなった {"obj":{123, 456.2...}} みたいなlongとdoubleの入り混じった感じの感じのオブジェクト。これはStringの配列にした。12sec->8.4secにした

最後によくよくデータ見直してみると重複した配列データを4つ受け取っていた。てへ なおして 8.4sec->2.9sec。

というわけでかなり速くなった。ちなみにShared Element Transitionがあると2.9秒でも意外と遅く感じない。その後大量の配列の取得は別APIに切り出した。これで1.2秒(18倍)。ちなみにiOSはそんなに時間かからないの謎…端末のスペックなのだろうか…

アプリの翻訳管理を楽にする / kosako さん

Rettyアプリは端末内の言語設定ではなく、アプリ内で言語切り替えするようなアプリ。

一般的にはstringファイル作ってNSLocalizedString("key", comment:"")みたいな感じでやってく?が、これはめんどくさい‥特にKeyの名前を名前を決めるのが面倒くさい typoするかもしれないし

Google SpreadSheetを使ってみた。Google Google Apps Scriptでspreadsheetからアプリ用のリソースファイルとswiftファイルを生成する。Googleのバックアップと同期を使ってローカルに自動DL。

同期はなんか拡張子が変になったり?するようなのでfswatchというのを使うといい。

kosakoさんのプロジェクトではNSLocalizedStringは使ってなくて Stringにlocalizedというextensionを生やして対応していた( "keyname".localized() )。まだtypoの危機があるのでenumを使うようにした。Localize.keyname.localized()みたいな。こうするとサジェストされて雰囲気で書けるようになるので良い。

Q. スクリプトは公開しないのか?

  1. Qiita にあるよ

qiita.com

Alexa、APKを配布して / horie1024 さん

speakerdeck.com

APKの配布方法、手動とかGradleとかCIとかあるが、音声でできたら便利では?と思った

流れ。alexa→LambdaでBitriseをトリガー、BitriseでDeploygate叩く。

スキル作るには呼び出し名が必ず必要で、今回は「Alexa,ビットライズでAPKを配布して」の形で使うのだが、呼び出し名がビットライズ、インテントが「APKを配布して」となる。トリガーにはBuild Triger APIをつかう。deploy workflowにScript Stepを追加して、ビルド完了後APKをアップロード。DeployGateでAPKを配布。アップロードされた。

これで音声コマンドでAPK配布までできるようになった。

Alexa、APKを配布してのような普通の人が使わないような言葉も認識してくれて良い。

iOSフレームワークViperのススメ / hirothings さん

speakerdeck.com

MVCのつらさ、工夫しないとルーティングがない、Viewのロジックとデータに関するロジックが交じる。

かっちりしたフレームワークが欲しいがスピードも犠牲にできない、そこでViper。

Viperは単一責任の原則に基づいて作られたフレームワークで、iOSの現場で生まれたフレームワーク

Viperの説明(省略)。

チームに持っていくときは、簡単なTwitterクライアントのサンプルを持っていって見てもらった

github.com

結果好感触だったので自信をもって進められた。

テスタブルになったのでStubとSpyを使ったユニットテストを採用した。

Presenter以外のレイヤーの実装に悩まされずに済んだ。

ボイラープレート増える問題に関しては、Kuriとかコードジェネレータを使うと良い。

RuntimePermissionChecker というライブラリを作った / taptappun さん

Runtime Permisson。コーディングしてたら Permission 書くの忘れてた、となって時間無駄にすること多い。

Permissionのこと考えたくない‥AndroidManifest.xmlにPermission記述したら自動的によろしくやって欲しい。

なので作った。細かい話や導入はQiitaにのっけているのですが、みんな使ってくれ!

qiita.com

感想とか

iOSAndroidも面白くて聞き逃せない!

f:id:kumamotone:20180222214817j:plain

懇親会もアーキテクチャの話とか質問とかフリーランスの話とかできて楽しかったです。

TachibanaKaoru さんの Xcode Behavior ですが、帰ってから gistにアップロードされていたスクリプトを実際にXcode Behaviorで実行してみました。

f:id:kumamotone:20180223002530p:plain

設定からスクリプトを指定して

f:id:kumamotone:20180223002554p:plain

実行

f:id:kumamotone:20180223002625p:plain

ウィンドウ開き直す

f:id:kumamotone:20180223002721p:plain

おぉ〜

お疲れ様でした

potatotips #47 に参加しました (ブログまとめ)

potatotips #47 のブログまとめ枠で参加させていただきましたのブログです。

f:id:kumamotone:20180124234919j:plain

オイシックスドット大地さんの会場。(移転されていたことに向かう途中まで気づきませんでした…)

f:id:kumamotone:20180124235305j:plain

隣の部屋はキッチンになっていて、そこで調理してくださったのであろう料理がとても本格的でおいしかったです。

以下発表内容です。間違いや気になるところなどあればご指摘ください。埋まっていない資料は公開されたのを見つけ次第反映します。

審査なしでiOSアプリのアイコンを変更する / Hideyuki Okuni さん

審査なしでiOSアプリのアイコンを変更する方法がある。

iOS10.3から使用可能な機能で、それ以前のiOSをサポートしている場合は if #available(iOS 10.3, *) {} を使う必要がある。

やり方は意外と簡単で、CFBundleIconsというKeyの設定をInfo.plistに追加して、アイコンをプロジェクトに追加、UIApplication.shared.setAlternateIconName()を使うだけ。このときアイコンはAssets.xcassetsではなく直接追加する必要がある。

注意点としては、これをやると「アイコンが変わりましたよ」的なアラートが出るので、ユーザーのヘイトが溜まらなさそうなタイミングを見計らってやったほうが無難。

qiita.com

Advanced Usecase for Codable / d_date さん

speakerdeck.com

Swift4からCodableというものが使えるようになった。これはJSONをEncode & Decodeできるもの。

デコードする機能ほうはよく語られていると思うが、エンコードの機能もなかなか便利。

たとえばキャッシュを作る時。サーバーからデータを取ってきたいが、サーバーにアクセス出来ない場合はキャッシュを返すようなときに、Encodableを使ってローカルに置いておくことで実現できる。Keychainにトークンを保存しておきたい場合もData型にすれば保存できるので簡単。

Swipe Transition / tattn さん

speakerdeck.com

画面のどこでもスワイプジェスチャーする機能を実装してみた(SwipeBackと呼ぶ。Sloppy Swipingとも呼ばれている)。あと下スワイプでモーダルを閉じるやつ(なんというのかわからないが今回はSwipeToDismissと呼ぶ)も実装した。

実装方法。まずUIPanGestureRecognizerという有名なクラスがあって、これで指の移動量を取得できるのでこれでスワイプを検出する。

また UIViewControllerAnimatedTransitioning プロトコルを使うと自作の画面遷移を実装できるので、これを使ってViewの表示位置を移動させる(SwipeBackなら右、SwipeToDismissでは下)。

UIViewControllerTransitioningDelegate はpresent/dismiss時に前述のUIViewControllerAnimatedTransitioningを指定するためのプロトコルで、SwipeToDissmissで自作の画面遷移を利用するために使用する。

UINavigationControllerDelegateはUINavigationで発生するイベントの補足や、前述のUIViewControllerAnimatedTransitioningを指定するためのプロトコルで、SwipeBackで自作の画面遷移を利用するために使用する。

UIPercentDrivenInteractiveTransitionは画面遷移の補完の指定や、画面遷移が何%完了しているのかを設定するクラス。これによってどこまでスワイプしたのかを表現する。

これらを組み合わせて実際にSwipeBackを実装する方法を紹介。このとき、遷移元のviewの下に遷移後のviewをinsertして、遷移後のviewにパララックス効果(これにより、遷移前と遷移後のViewを異なるスピードで動かすことで、立体感や奥行きを演出する)を付けつつ遷移前のviewを右へ移動することで自然なアニメーションを実現している。少ないコードで実現できた。

github.com

せっかくなのでライブラリ化した。ScrollViewがあっても動作するようにしたり、Method Swizzlingですべての画面に適用する機能も備えている。

UXデザインをやるやらないで変わったUIの精度 / HaraguchiYumiko さん

UXデザインの手法を取り入れたらUIが洗練された話。

動画から指定した位置の静止画を切り出せるという、スナップショット機能という機能を作り、その後指定した範囲の動画を切り出せる機能を作ることになった。

UXデザインの手法を取り入れ、ユーザーストーリーを考え→ユーザーテスト→ユーザーテストを反映→再度ユーザーテストすることにした。

ユーザーストーリーを取り入れたことにより、操作に統一感が出てきた。その後ユーザーテストを行いUIを洗練した(このとき15名ぐらいにお願いしたのだがこの機能の場合5名ぐらいで良かったという気づきがあった)。

UXデザインを導入することで、洗練されたUIを提供しながら、UIデザインで正解がわからなくなったときの判断材料として使えるようになるので、時間は掛かるが、UIを洗練するためには良い。ユーザーストーリは簡単な機能の追加でも有効だと思うので試して見ると良い。

初めてのSwift Intermediate Language / kitasuke さん

Swift のコードは実行ファイル(.o)になるまでに以下のようなフェーズを踏んでいる。

(【】で囲んであるのがコンポーネント、囲んでないのが成果物) 【lib/Parse】→AST→【lib/Sema】→ (type checked) AST→【lib/SILGen】→(raw) SIL→【lib/SILOptimizer】→canonical SIL→【lib/IRGen】 →LLVM IR→【LLVM】→.o

発表では、局所変数を定義して、代入したものを返すような簡単なコードが、SILになったときどんな感じになるのかというのを紹介。

またSILOptimizerが通常やる最適化以外にも、コンパイラに-Oオプションを付けた場合のOptimizeもあって、格納しても使われない変数なんかがある場合はアドレスそんまま返すとかをやってくれる。

SIL、思ったより難しくないし、最適化の仕組みが知れるのはなかなかSwiftエンジニアとして良いと思うのでおすすめです。とくに最適化の部分。

詳しく知りたい場合はswift/docs/SIL.rst などを読むと良い。

github.com

ほか参考資料

qiita.com

qiita.com

既存のプロジェクトに、Firestoreを導入してみた / sun54907 さん

speakerdeck.com

FireStoreはオフライン、リアルタイム更新にも対応するデータベース。Firebase Realtime Databaseの後継でまだbeta。

開発合宿をやったときにFireStore導入しようという話になった。

普段できないことを取り組むというやつで、sun54907 さんのチームではリアルタイム通信を導入することにした。リアルタイム通信の方法はいくつかあって、WebsocketとかRealmとか使う方法もあるけど、websocketを自前実装するのは大変そうだし、外部サービスにメッセージ等の個人情報を置くのも嫌。

そんなとき、「マッチングアプリにつきまとう状態管理のつらさ」というLT資料を見つけた。

speakerdeck.com

これは最終的にFirebaseに新着件数だけを置いて、その更新をフックして既存のAPIを叩くということをしており、今回のケースにもマッチすると思ったので採用することにした。

ユーザー認証も必要なのでFirebaseのAuthを使った。サーバーから得られたカスタムトークンを使うことで認証できる。

この方法を使えば2日程度で実装できるほど簡単だが、現時点ではβ版なので動作保証されない(SLAもない)ことに注意。

Introducing Relax -- A release tool for Xcode / SCENEE さん

Swift言語とSwiftという上下昇降デスクにハマってらっしゃるSCENEE さん。

www.okamura.co.jp

Relaxというツールを作ったのでその紹介。

アプリ申請時、xcodebuildでAutomatic Signing/Manual Signingでハマったとか、ipaに想定と異なるProvisioning Profileが入ってるとか、色々ハマりどころがある。

github.com

Relaxを使うと、Relfileという名前のYAMLを置くだけで、Codesignエラーに悩まされることなく、IPAファイルを作成することが出来る。

brewで入る。xcarchive, ipaの作成だけでなく、ValidateコマンドでArchiveした後のIPAを簡単に検証したり、別のProvisioning Profileを使ってipaのresignをしたり、ほかにも色々機能がある。

感想

今回はiOSの発表がめちゃくちゃ続いて(potatotipsはAndroidiOSの発表が交互にやられるので、いつもはAndroidの発表を聞きながらiOS側の発表を咀嚼しつつまとめるみたいなことをしてた)、まとめるのはちょっと大変でしたが、勉強になって楽しかったです!