🍫cocoapods-app_group: AppGroupを用いたチーム開発補助
要約
iOS - 個人用アカウントでAppGroupを用いたチーム開発を行なう - Qiitaで書いた内容をCocoaPodsプラグインにした。
やりたいこと
問題点と解決方法は、Qiitaに書いた記事と同様のため、引用ですませる。
問題点
iOS8でアプリ間でデータを共有する仕組みとしてAppGroupが導入された。カスタムキーボードやAppleWatchアプリ等の拡張は別アプリとなるため、これらを開発をする際はAppGroupの利用が事実上必須である。 (参考: http://www.toyship.org/archives/1845)
AppGroupは開発者アカウントごとのデータであり、かつ、世界中で一意となる名前を持たねばならない。 個人(Individual)アカウントは複数人で共有できないため、同じAppGroupを使うことができない。企業(Company/Organization)アカウントならばAppGroupの共有が可能だが、取得には法人である必要がある。
そのため、法人でない団体(例: 大学サークル等)では、AppGroupの利用が難しい。
解決策
以下の方針で、開発を複数人で行なえるようにする。
- 開発者ごとにAppGroup名/Bundle Identifierを変更する。
- AppGroup名/Bundle Identifierを具体的に書く箇所を一箇所にすることで、容易に変更できるようにする。
ただし、AppStoreに提出できるのは誰か一人という制約は解決できないため、誰かが正式版のビルド係/AppStoreへの提出係となる必要がある。
インストール
gem install cocoapods-app_group
初期設定
1. Podfile への追記
Podfile
に以下のように書いて、プラグインを有効にする。
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' use_frameworks! plugin 'cocoapods-app_group'
2. App group名の指定
app group名を指定したのち、インストールする。
pod app-group GROUP_NAME
pod install
3. AppGroupを有効にする。
各ターゲットのcapabilityからAppGroupを有効にする。 その際、名前としてgroup.$(APP_IDENTIFIER)
を用いる。
使い方
import AppGroup AppGroup.userDefaults().setInteger(42, forKey: "answer") let n = AppGroup.userDefaults().integerForKey("answer")
JAWS-UG 名古屋 in AWS Cloud Roadshow 2015「Amazon EC2 スポットインスタンスを開発環境にする話」
キンドル(本物)がとどいたー。 pic.twitter.com/kNckUW3IzL
— mzp (@mzp) November 4, 2015
JAWS-UG 名古屋 in AWS Cloud Roadshow 2015 でLTをした。優勝してKindleをいただいた。
スライド
発表原稿
タイトルだけでだいたい内容が分かる気がしますが、話を進めます。
自己紹介
簡単な自己紹介をすると、TwitterIDはmzpです。MisocaというWebサービスを作る仕事をしています。このインフラにはAWSを利用していますが、今回はその話ではありません。ボク個人が使っているAWSの話です。
MacBook
ところで、先日、新型のMacBookを買いました。解像度が高くなり、軽くなり、バッテリーの持ち時間も伸びました。最高です。この資料もそのMacBookで作りました。
性能の低下
その反動として、マシンの性能が低下しました。 ベンチマークのスコアでみるとこんな感じです。
Intel Core M-5Y31&M-5Y71を搭載した新しいMacBook Retina 12インチモデルのGeebBenchスコア比較まとめ。 http://t.co/U1OrlqizRc pic.twitter.com/8quOSPO1PQ
— Appleちゃんねる (@applechinfo) April 3, 2015
前に使っていたのは2011年モデルのMacBookAirなので、ベンチマークスコアが少し落ちています。 言い換えると、4年前のPCを最新機種に買い変えたら、性能が若干落ちました。
開発に支障がでた
弊社のMisocaはRailsで開発されています。ゲーム系の開発などに比べるとマシですが、Railsの開発にもそれなりにの性能が要求されます。 それをこのMacBookで行なうのはかなり厳しいです。 念のため補足すると、オフィスにいるときは会社のiMacが使っているので特に不都合はない。困るのは、自宅で作業するときや、旅先で作業するときですね。
AWS EC2 スポットインスタンス
性能のいるマシンを必要なときだけ使うといえばAWSです。Amazon Workspaceで仮想デスクトップを使うのが定石な気もしますが、今回はEC2スポットインスタンスを使いました。
主な理由は以下の2つとおりです。
- 開発ではターミナルしか使わないのでsshで接続できればよい。
- 安い。
まあ、あとはスポットインスタンスを使ってみたかった、というのもあります。
費用
いつも使うc4.large((2CPU; メモリ 3.75GB)がだいたい0.02ドル/Hなので、一日8時間*20日使ったとしても3.2ドル程度です。もし倍必要になったら、その人はちょっと働き方を見直したほうがいい気がしますね..。働きすぎないようにBilling Alertで監視してもよいかもしれません。
構築時のコツ
構築する際のコツとしては
- AMIを事前に作っておく。
- 別途、EBSボリュームを作り、消えたら困るデータはそちらに置く。
- ポートは多めにあけておく。特に1024番以上はあけておいたほうがよいです。
詳しくはブログに書きました。 http://mzp.hatenablog.com/entry/2015/04/25/110043
ちなみに最初はこれをやらずに、毎回1からchef-soloで環境を作ってコードを書く、ということをやっていました。
利点
いざ使ってみると、思ってもいなかった利点がありました。
- マシンがAWS上にあるのでバッテリーが異様に持つようになりました。重い処理を回しまくっても、バッテリーが減らないのは快適ですね。
- 同じくAWS上にあるので、ネットワークもかなり速くていいですね。通信量も抑えられるので、テザリングしてても安心ですね。
- 開発に使うデータはそれほどセンシティブなわけではないんですが、ローカルにデータを保持しないのは安心感があります。
欠点
もちろんスポットインスタンスを使っているので、いつシャットダウンされるかわからないのは困った点です。 何度か価格の急騰に巻き込まれたりしました。 このときは一気に10倍近く値上がったときのやつです。
スポットインスタンスを開発環境にするのを試してたけど、価格が暴騰して死亡した。 pic.twitter.com/8Uww1Lmwv1
— mzp (@mzp) March 20, 2015
EBS上のデータは保持されますし、大事なコードそのものはgithub上にあるので、実際は困ることはそれほどありません。が、いつシャットダウンされるか分らないというのは精神的にキます。
まとめ
そろそろ時間なので、簡単にまとめます。
📷 mov/jpegからのLive Photo生成
「LivePhoto、外にでて猫とか撮らないと活用できないと思ってた。でも、movとjpegから生成できるようになれば、インドアでも十分使える。むしろインドア最高」ってばんじゅんさんが言ってて、ちょっと感動した。
— mzp (@mzp) October 5, 2015
要約
MOV動画とJPEG画像からLive Photoを生成するLoveLiverというツールを作った。
Live Photos の仕組み
Live PhotosはQuickTimeフォーマット(mov)とJPEG画像を組合せすることで実現されている。 TechCrunchのReview: Apple’s iPhone 6s And 6s Plus Go ‘Tick’ | TechCrunchの図が分かりやすい。
(http://techcrunch.com/2015/09/22/review-apples-iphone-6s-and-6s-plus-go-tick/#.ngcoh9:5tnw より引用)
ただ、図では45フレーム固定のようになっているが、実際には固定されていない。 iPhone 6sで撮影すると45フレームになるが、Live Photos自体はもっと長時間再生できる。 また、AppleWatchに転送して文字盤に設定した場合は、先頭20フレームくらい*1しか再生されない。
Live Photo の作り方
iOS
iOS 9.1でLive Photoを操作するAPIの追加が予定されている。ベータ版のiOSで利用可能になっているため、LivePhotoDemoのようなデモアプリが作成されている。
ただ、LivePhotoの再生等はできるが、フォトアルバムに保存することは実現できていないらしい。 この問題については Saving to Camera Roll #3 で議論されている。 ボクもいくつか試してみたが、保存は実現できていない。
iOS 9.1が正式にリリースされることには保存もできるようになっていると思う。
MacOS X
El Capitan の Photos.app(写真アプリ)でmovとjpegをまとめてインポートすると、1つのLive Photo としてインポートできる。
このとき、結びつけられるmovとjpegは以下の条件を満す必要がある。
- 拡張子を除いたファイル名が一致する。(例:
IMG_0042.JPG
とIMG_0042.MOV
) - JPEGとMOVのメタデータに共通のUUIDが保存されている。
- MOVのメタデータに
com.apple.quicktime.still-image-time
が保存されている。- metadataトラックとして保存する。
- 値の意味はよくわかってない。
この条件については、先程のIssues内で報告されている。
また、LoveLiverもこの仕組みを使っている。
その他メモ
ffmpegによる変換
ffmpeg でLive Photos用のmovを作るには、以下のようにする。
ffmpeg -r 15 -i source.mov -r 15 -an -vcodec h264 -pix_fmt yuv420p composed.mov
フレームごとに選びたい場合は、いったん画像に分割して必要なものを選ぶとよい。
ffmpeg -i source.mov frame%d.png # 必要な画像ファイルを45枚選ぶ ffmpeg -r 15 -i frame%d.png -r 15 -an -vcodec h264 -pix_fmt yuv420p composed.mov
Live Photo に向いてる動画
- 15fpsなので動きがおだやかなもの。
- 縦長の動画。
- 高解像度の動画。 ホーム画面・ロック画面は縦向きなのでフルHDでも若干不足である。
デレステのMV、シネマグラフィクス(一部だけ動くGIF動画)などをためしたが、しっくりこなかったのでMMDで動画を作成した。
そしてこうなります。LivePhoto最高!! pic.twitter.com/La5oeiXojD
— mzp (@mzp) October 8, 2015
*1:厳密な数字は未確認
📦AquaSKK 4.2.7: SKK日本語入力FEP互換の記号入力
@tadsanさんの SKK日本語入力FEP互換の記号入力用ルールを取り込み、AquaSKK 4.2.7をリリースした。有効にすると z6
で ☆
が、z'
で ♪
が入力できる。
ダウンロード
https://github.com/codefirst/aquaskk/releases/tag/4.2.7
その他: PyCharm対応
同時にJDKがバンドルされたPyCharmで、aiueoの入力がうまくいかない問題にも暫定的に対処している。バグ報告は出したので、そのうちちゃんと直ることを期待している。
その他のInputMethodは「未確定文字列→確定文字列」の順で入力がなされる。一方、SKKの場合は直接確定文字列が入力されるケースがいくつか存在する。(例: ひらかな入力モードにおけるaiueoなど)。 このケースを正常にハンドリングできていないのが原因だと考えられる。
そこで、特定のアプリケーションの場合は、直接確定文字列を挿入するのではなく同様の内容の未確定文字列を直前に挿入するワークアラウンドをいれた。
🐥(\( ⁰⊖⁰)/) face for Apple Watch
に影響されて、Apple Watchの文字盤用の画像を作った。
利用例
ダウンロード
手元に38mmモデルしかないので、42mm版は勘で作っている。 ずれていたら、なんとかしてほしい。
使い方
- 上記画像をiPhoneに保存する
- お気に入りに設定する
- AppleWatchの文字盤切り替えから「写真」を選ぶ
- 上記の画像を選択する
- (\( ⁰⊖⁰)/)
ライセンス
- help/esa.io ロゴデータ - docs.esa.io にあるデータを利用している。
その他: 開発の流れ
⚡️Brew Sparkling: homebrew for iOS
自分のiOSデバイスなら開発者ライセンスなして、アプリを動かせるようになるので、自動でコードを落してきてビルドして転送するタイプのアプリ配布補助をだれか初めてほしい。「brew install ios/hoge」でイスントールできる感じ
— mzp (@mzp) 2015, 6月 10
Xcode7 からApple Developer Programに参加しなくて、iOSアプリの実機デバッグが可能になった。
これを利用し、Github等で公開されているソースコードをダウンロードし、自分のiPhoneにインストールするHomebrew拡張を作った。 例えば brew sparkling install SparkingSample
でサンプル用のアプリケーションがインストールされる。
主な用途としては、次のようなアプリケーションの配布を想定している。
- 進捗時計のような雑なアプリケーション。AppStore審査を通さない分、気軽に公開できるようになる。
- Provenance(マルチエミュレータ)のようなAppStoreの審査を通過できないアプリケーション。
準備
必要なもの
初期設定
- Xcodeを起動し「Preferences -> Accounts」から、AppleIDを登録する。
- 右下の「View Details」をクリックし、表示された画面で「iOS Development」のSigning Identifiesを作成する
使い方
インストール
brew install codefirst/sparkling/brew-sparkling
Xcodeを再起動すると、プラグインをロードするかを確認されるので、「Load bundle」を選択する。
設定
Xcodeの情報を正しく接続できているかを確認する。
# アカウントの確認 brew sparkling accounts # 証明書の確認 brew sparkling certificates # 接続されているデバイスの確認 brew sparkling devices
適当なものを選び環境変数に設定する。自分の場合は以下のようにしている。一個しか表示されないなら特に設定は不要のはず。
export BREW_SPARKLING_USERNAME=brew_sparkling@icloud.com export BREW_SPARKLING_CERTIFICATE='iPhone Developer: brew_sparkling@icloud.com (xxxxxx)' export BREW_SPARKLING_DEVICE=mzpPhone
iOSアプリのインストール
iPhoneがロックされているとインストールできないので、自動ロックはオフにしておいたほうがよい。
インストールできるアプリケーションの例
Firefox for iOS
Firefox for iOS。現時点ではまだリリースされていないがソースコードが公開されているため、Sparklingでインストールできる。
インストール方法:
brew sparkling install Firefox
JapaneseKeyboardKit
Google日本語入力から派生したMozcをiOSに移植したキーボード。 JapaneseKeyboardKit·Mozcを使ったiOS8用カスタムキーボード MOONGIFTなどで紹介はされているが、AppStoreでは配布されていなかった。
インストール方法:
brew sparkling install JapaneseKeyboardKit
SpoolDays
指定した日付からの経過日を表示するアプリケーション。AppStoreで公開していない理由を作者である@suerさんに聞いたところ「怠惰」とのこと。
インストール方法:
brew sparkling install SpoolDays
Provenance
SNES、Sega Genesis、Game Gearなどのマルチエミュレータ。ここでは、スーパーファミコンのプログラムを書きたい - ポルノアニメのROMを動かしている。
インストール方法:
brew sparkling install Provenance
その他
インストール可能なiOSアプリは brew sparkling list
で一覧表示できる。もしくはGithubレポジトリを見てもよい。
その他
制限
- Capabilityが利用できないため、位置情報の取得、バックグラウンド再生、アプリ内課金などの機能は利用できない。
- 3ヶ月で有効期限が切れるため、定期的に再インストールが必要。
関連リンク
謝辞
欲しいものリストにあったSparklingがたくさん届いた https://t.co/wvLcgQTql6 pic.twitter.com/lPr1PhuavJ
— ばんじゅん(!!) (@banjun) 2015, 8月 10
Xcodeの挙動を解析するときに@banjunさんにものすごくお世話になったので、Sparklingっぽいものを贈っておいた。
📚Prpr設計判断
🍮 Prpr: bot for github pull requestに、こういう設計にした理由について書くのを忘れていた。
gemプラグイン
gemで動作を追加できるようにするのは当初から計画していた。ただ、まずは一つのgemとして作って後から分割するか、最初から複数のgemとして作るのかは迷った。
結局、最初から複数のgemとして作ることにしたが
- gemspecを大量に書くのが面倒だった。
- どこでからがプラグインかが明確になって、クラス設計等がしやくなった。
- 外部のAPIを叩く部分をすべてプラグインにしたので、本体のspecでモックが不要になった。
といった効果があったので、よい選択だったと思う。
設定ファイル
prpr-checklistなどでは、投稿する文書を設定できるようにする必要があった。ただ、環境変数で設定するようにすると、設定を変更できるのが一部のユーザのみになってしまう。
そこで投稿する内容はレポジトリ内にあるファイルで設定できるようにした。(標準では CONTRIBUTING.md
の内容が投稿される。)
一番最初のアイデアではWikiを使うつもりだったが、内容を取得するAPIが見あたらなかったので断念した。
Github限定
プラグインでやりたいことがかなりGithubに依存しそうだったので、対象をGithubに限定した。 レポジトリを操作する抽象レイヤーなどは作らず、プラグインにはOctokitのインタフェースを直接露出している。
対照的にprpr-review_labelの通知先は、特定のサービスに限定していない。これはできることを「テキストの通知」に限定したので、抽象レイヤーを容易に作れたためである。