xcconfig を使い本体アプリと Embedded Framework を同じ環境設定でビルドする

本体アプリを Build した時に、本体アプリの CONFIGURATION を Embedded Framework 側に渡したい。

  • 本体アプリを Debug Build
    • Embedded Framework も Debug Build
  • 本体アプリを Release Build
    • Embedded Framework も Release Build

というように、本体アプリのビルド環境によって自動で Embedded Framework のビルド環境も変えたい。

xcconfig を使う

  1. Embedded Framework 側で xcconfig を作成する
    • New File から Configuration Settings File を選択
    • Targets は Embedded Framework を選ぶ
  2. hoge.xcconfig に下記を追記
    • OTHER_SWIFT_FLAGS = "-D" $(CONFIGURATION)

これでビルドすると、本体でビルドした環境を Embedded Framework 側に渡せる。

参考

The Unofficial Guide to xcconfig files

ここにサンプルやユースケースなど色々書いてあって便利。 今回は CONFIGURATION を渡したが、他にも色々な設定ができる。

TodayViewController の viewDidLoad が呼ばれるタイミングについて

iOS の TodayExtension を実装していて、 TodayViewController の viewDidLoad が走るタイミングが最初はわからず苦労した。

viewDidLoad が呼ばれるタイミング

画面に表示されたタイミングで ほぼ毎回 viewDidLoad が呼ばれる。
TodayExtension を 10 こくらい並べて、スクロールして画面外から表示させても viewDidLoad が呼ばれる。

開発し始めた最初は

  1. 端末起動後/Widget 追加後に viewDidLoad が 1 度だけ呼ばれる
  2. 画面表示時に widgetPerformUpdate(completionHandler:) が呼ばる
    • 更新の必要があれば completionHandler(.newData) を実行する

だと思って開発を始めたため、何度も viewDidLoad が呼ばれて戸惑った。

TodayExtension の高さを変えるような時に問題が生じる

TodayExtension Widget 表示時、こう動く。(TableView で、 List の要素 1 つにつき 50px 使うようなコードだとする。)

  1. 一瞬だけ前回取得したデータが表示される
    • 要素が 4 つあったので、 height が 200px くらいある
  2. Extension の表示が初期表示になる
    • 初期は要素数が 0 なので、 height がデフォルト(110px)になる
  3. 取得されたデータが表示される
    • しかし、 Show More になっているのにデータが2つしか表示されない…

Show More の状態は変わらないが画面はリセットされてしまい、表示がおかしい…。
こんな感じ。

f:id:star__hoshi:20170720140917g:plain

表示を改善するためには?

初期表示時に前回取得したデータを表示すれば良い。

  1. 一瞬だけ前回取得したデータが表示される
    • 前回の height が 200px だったので、それがそのまま表示される
  2. Extension を初期化する
    • 初期化時にローカルに保存しておいたデータを表示する
      • 画面に変化がないので height 200px を保つ
  3. 取得された最新のデータを表示する
    • 素数が 4 つだったので、 height が 200px になる
    • 取得したデータをローカルに保存しておく

つまり、前回取得したデータを保存しておいて、 viewDidLoad 時にそのデータを描画するとユーザとしては画面がチラチラせずに違和感なく使える。

そうすると初期化時に高さが前回と同じに設定されるので、突然小さくなったりしないですむ。

↓のは画面に変化がないように見えるが、実際には画面が初期化されたりしている。

f:id:star__hoshi:20170720140853g:plain

ローカルにデータを保存

保存したいデータが String だけとかなら楽でいいけど、実際は JSON Mapping されたクラスだったりするので、そのクラスに NSCoding を継承して data 型として保存すると楽。

UserDefault などに class を保存するサンプル

ちなみに TodayExtension で UserDefaults を使うには AppGroups の設定が必要。

おわり

最初は viewDidLoad が呼ばれまくることに違和感があるが、 UserDefaults などを使って適切にデータを管理すればそんなに難しくなかった。

しかし Show More / Show Less の挙動とかうまくいかないところとかあってなかなか難しい…。

EdTech Engineer Meetup #1 で「学校の iOS 端末事情」について話した #edtech_ja

Education×Technolog 業界の3社 Classi, LITALICO, Studyplus が集まって会社紹介やらパネルディスカッションやら LT やら懇親会しましょう、という会で LT してきた。

edtechem.connpass.com

Lightning Talks

教育業界、というか BtoB 業界のモバイルアプリは辛い話が結構あって、その 1 つに MDM がある。

やっぱり他の会社の人も同じ悩みを抱えている人がいて「その辛さわかる…」と言ってもらえて、共感してもらえたっぽくて嬉しい。

「ウチはめっちゃテストして安定している Version を MDM で提供するようにしている」という話を聞いて、うちも MDM 提供バージョンは固定したほうがいいのかもなあと思った。

今回は MDM によるアプリバージョン固定化問題について話したけど、他にも

  • 端末共有問題
    • 複数人の生徒が1台のデバイスを使う
    • 端末使い終わった後にログアウトし忘れると…?
    • Keychain Sharing しちゃうと、意図しないユーザでログインしてしまう
  • MDMSafari 無効化しているはずなのに Safari 使えちゃう問題
  • 強制アップデートがめっちゃ大変

など、 toC だとあまり考えなくて良いことが toB だと大きな障壁になるケースがあり、なかなか大変な業界である。

勉強会それ自体について

開始が 18:20 予定だったのが、実際には 18:40 開始になった。人の入りがあまりよくなかったので開始を遅らせたらしいが、特にアナウンスなどはなくただ gdgd と開始が遅れているように見えて、参加者だったら印象良くないだろうなあと思っていた。開始遅れるならそのタイミングでアナウンス入れたり、画面に理由を表示したりとかしたほうが良さそうに思った。

また、勉強会の運営側を初めて目の当たりにしたが、とても大変そうだった。昨今騒がれている勉強会をドタキャンする人は運営側になったことがないのだろう。
自分は LT 参加者の軽い気持ちで参加してしまったのであまり貢献できなかった、もうちょっと能動的に動ければよかったと反省である。

しかし懇親会は盛り上がっていた? ように見えたので、終わりよければ全てよし。

Firebase, Google Analytics, Fabric, Apple App Analytics の個人的使い分け

昨今モバイル界隈ではアクセス解析に色々なサービスがあるが、それぞれにメリット/デメリットがあるため、複数併用するようにしている。4 つのサービスの個人的使い分けについて、iOS エンジニア視点で雑に書いていく。

なお、どれも無料枠での利用とする。

最初にまとめ

  • ざっくり見たいときは Firebase を使う
  • 細かく見たいときは Google Analytics を使う
  • クラッシュ情報とリリース直後の状況を見たい場合は Fabric を使う
  • 上記以外のデータが見たい場合は Apple Analytics 使う

Firebase

メリット
  • モバイルに特化しているので見やすい
  • バージョン、コホート、デバイスなどデフォルトで多くの情報を取ってくれる
  • ぱっと見いい感じにデータを見してくれる
  • 最近入った STREAMVIEW というのがリアルタイムで使っている人を見れる
デメリット
  • Screen Transition が見れない
    • GA で補完
  • 詳しい情報を見たい場合は BigQuery 連携が必要
    • ぱっと見はいいけど詳しいところまで見れない
      • 例えば iOS8 のユーザ数が見れない

Google Analytics

メリット
  • 細かい情報まで見れる
    • このカテゴリの人のこの情報 みたいな細かい指定ができる
  • Screen Transition が見れる
  • リアルタイム View が見れる
デメリット
  • 細かい情報まで見れるけど、気が利かない
    • iOS8 のユーザ数見たかったら、8.0 と 8.1 の数字出してくれてあとは自分で計算するとか
  • なんかぐちゃぐちゃしてて見づらい

Fabric

メリット
  • Crashlytics のクラッシュ情報が見やすい
  • Latest Release でアプリのリリースに問題ないかが確認できる
デメリット
  • Growth でユーザ分析ができるが、Firebase の方が見やすい
    • なんかいまいち直感的に見れない
  • Google に買収されてそのうち消える

Apple App Analytics

メリット
  • ソースから、どこ経由でインストールされたかが見れる
  • アプリのダウンロード数(ユニット数)が見れる
  • リテンションやセッション数、アクティブ数など結構情報が見れる
デメリット
  • まず iTunes Connect 開くのが面倒
    • ログインしてアプリ開いて分析ページまで遷移して...がだるい
  • オプトインのみの情報しか見れない
    • 30%がオプトインだから3倍ちょっとすれば数字が出るな...
      • と頭の中で計算している

おわり

どれも便利なんだけど、いいところもあれば足りない機能もあり、結果として色々なサービスを使ってしまっている。
Firebase には一番期待していて、Fabric は Google に買収され Crahslytics が Firebase と統合されると発表があったし、STREAMVIEW というのが素晴らしく便利な気がしている。
STREAMVIEW があれば Screen Transition を取る必要もなくなるかもしれないので、とにかく Firebase に頑張ってほしい。

モバイルアプリの情報管理・Slack 連携ができる AppFollow

AppFollow

f:id:star__hoshi:20170703172347p:plain

アプリのレビュー、ランキング、説明文など色々な情報を総合的に見ることができて、それらの情報を Slack などに連携できる。iTunes Connect のアカウント情報などは渡す必要がなくて、AppStore などで見れるデータをそのまま保存している。
2 アプリまでなら無料。

主にアプリのレビューを Slack に流すのに利用している。

レビュー

レビューが来たらこんな感じに Slack 通知が見れて良い。ラグは数時間くらいな気がしているが気になったことはない、 Apple の反映がそもそも遅い。

f:id:star__hoshi:20170703171949p:plain

説明文

アプリの説明文を変更したら、こんな感じで diff が見れる。

f:id:star__hoshi:20170703171956p:plain

アプリのスクショを変更しても古いの保存しといてくれるし、自動でいろいろバージョン管理されて素晴らしい。

無料枠

アプリが2つまでしか登録できない以外は特に困ったことはない。
1つのアカウントにつきアプリが2つまでだが、 AppFollow はアカウント量産という手段が使えてしまう。しかし良いサービスなのでちゃんとお金を払いましょう。

この記事

後から読み直したらすごい PR のような記事になってしまった。
とても便利なのでみんな使おう、という意志以上のものはありません。

Mac の環境構築手順を整備した

今までも dotfiles と Brewfile を Github に置いて環境構築手順を整えていたが、 dotfiles は homesick、 Brewfile は homebrew-file というのを使っていたため管理がややこしくなっていた。

しかもそれらは全然 commit してなくて古くなってしまったため、エイヤで色々整えることにした。

Brewfile

homebrew-file を使うのはやめ、素の Brewfile を Github で管理するようにした。
下記コマンドで Brewfile を吐き出すことができる。

$ brew bundle dump --force

次回 brew のセットアップをするときは下記コマンドでいける、はず(試してないので本当にいけるかわからない…)。

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
$ git clone git@github.com:starhoshi/Brewfile.git
$ brew tap Homebrew/bundle
$ brew bundle --file=Brewfile/Brewfile

dotfiles

必要な設定ファイルをレポジトリ管理するようにした。karabiner, hammerspoon の設定ファイルは実際には dotfile ではないかもしれないが、難しいことを考えるのはやめた。

これらの設定ファイルは↓のコマンドで install できる、はず。
zsh がすでに install されているのが前提なので、 brew の後に実行する必要がある。

$ git clone git@github.com:starhoshi/dotfiles.git
$ ./dotfiles/install.sh

dotfiles の設定では Deploy と Initialize を分けろとあるが「そこまでガチ勢じゃないしこのままでいいか」と思い, install.sh すればいい感じになるようにした。

まとめると

次回のセットアップでは、

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
$ git clone git@github.com:starhoshi/Brewfile.git
$ brew tap Homebrew/bundle
$ brew bundle --file=Brewfile/Brewfile
$ git clone git@github.com:starhoshi/dotfiles.git
$ ./dotfiles/install.sh

これで環境が整うようになった。

レポジトリ

参考

Swift2 から Swift3 への移行がだるすぎて諦めた

1年前くらいにリリースしたアプリ があるのだが、動かなくなったというレビューがきたので修正しようと思ったのだがだるすぎる。
何がだるいかというと、 Swift3への対応が一番だるい。ライブラリを更新して、マイグレーションして… ってやらないといけないけど、そもそもライブラリがSwift3対応してなくて諦めた。

だるさ

  • Swift3移行がだるい
  • Swift3対応していないライブラリがある
  • xml, html の parse がだるい
  • 過去の自分のコードがイケてなくて読むのがだるい
  • 利用者があまり多くないので作り直してもメリットが小さい
    • レビューで「動かなくなってつらい」ってきたので利用者はいる

結局

Xcode 7.2.1 をダウンロードして、Swift2 で修正することにした。
いつまでも Xcode7 で修正できるわけではないし、Swift3の移行はだるすぎるし、そのうちこのアプリは死ぬだろう。

悲しいが、 Apple 様の進化に追従できなかった者の末路である。しょうがない。