みずぴー日記

人間の再起動ボタンはハワイのビーチにある

🍫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) を用いる。

f:id:mzp:20151103222826p:plain

使い方

import AppGroup

AppGroup.userDefaults().setInteger(42, forKey: "answer")

let n = AppGroup.userDefaults().integerForKey("answer")

それ以外のメソッドソースを見たほうが早い。

JAWS-UG 名古屋 in AWS Cloud Roadshow 2015「Amazon EC2 スポットインスタンスを開発環境にする話」

mzpさんがJAWS-UGでLT優勝してkindle 貰ってきた件の目録がこれです。#jawsug

A photo posted by Dominion525 (@dominion525) on

JAWS-UG 名古屋 in AWS Cloud Roadshow 2015 でLTをした。優勝してKindleをいただいた。

スライド

発表原稿

タイトルだけでだいたい内容が分かる気がしますが、話を進めます。

自己紹介

簡単な自己紹介をすると、TwitterIDはmzpです。MisocaというWebサービスを作る仕事をしています。このインフラにはAWSを利用していますが、今回はその話ではありません。ボク個人が使っているAWSの話です。

MacBook

ところで、先日、新型のMacBookを買いました。解像度が高くなり、軽くなり、バッテリーの持ち時間も伸びました。最高です。この資料もそのMacBookで作りました。

性能の低下

その反動として、マシンの性能が低下しました。 ベンチマークのスコアでみるとこんな感じです。

前に使っていたのは2011年モデルのMacBookAirなので、ベンチマークスコアが少し落ちています。 言い換えると、4年前のPCを最新機種に買い変えたら、性能が若干落ちました。

開発に支障がでた

弊社のMisocaはRailsで開発されています。ゲーム系の開発などに比べるとマシですが、Railsの開発にもそれなりにの性能が要求されます。 それをこのMacBookで行なうのはかなり厳しいです。 念のため補足すると、オフィスにいるときは会社のiMacが使っているので特に不都合はない。困るのは、自宅で作業するときや、旅先で作業するときですね。

AWS EC2 スポットインスタンス

性能のいるマシンを必要なときだけ使うといえばAWSです。Amazon Workspaceで仮想デスクトップを使うのが定石な気もしますが、今回はEC2スポットインスタンスを使いました。

主な理由は以下の2つとおりです。

  1. 開発ではターミナルしか使わないのでsshで接続できればよい。
  2. 安い。

まあ、あとはスポットインスタンスを使ってみたかった、というのもあります。

費用

いつも使う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倍近く値上がったときのやつです。

EBS上のデータは保持されますし、大事なコードそのものはgithub上にあるので、実際は困ることはそれほどありません。が、いつシャットダウンされるか分らないというのは精神的にキます。

まとめ

そろそろ時間なので、簡単にまとめます。

📷 mov/jpegからのLive Photo生成

要約

MOV動画とJPEG画像からLive Photoを生成するLoveLiverというツールを作った。

f:id:mzp:20151011171740p:plain

Live Photos の仕組み

Live PhotosはQuickTimeフォーマット(mov)とJPEG画像を組合せすることで実現されている。 TechCrunchのReview: Apple’s iPhone 6s And 6s Plus Go ‘Tick’ | TechCrunchの図が分かりやすい。

f:id:mzp:20151011161325j:plain

(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.JPGIMG_0042.MOV)
  • JPEGとMOVのメタデータに共通のUUIDが保存されている。
    • JPEG: ExifのMakerNote内の kFigAppleMakerNote_AssetIdentifier ("17") に対する値として保存する。
    • MOV: mov自体のメタデータcom.apple.quicktime.content.identifier に対する値として保存する。
  • 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で動画を作成した。

*1:厳密な数字は未確認

📦AquaSKK 4.2.7: SKK日本語入力FEP互換の記号入力

@さんの SKK日本語入力FEP互換の記号入力用ルールを取り込み、AquaSKK 4.2.7をリリースした。有効にすると z6 が、z'が入力できる。

qiita.com

f:id:mzp:20150927090026p:plain

ダウンロード

https://github.com/codefirst/aquaskk/releases/tag/4.2.7

その他: PyCharm対応

同時にJDKがバンドルされたPyCharmで、aiueoの入力がうまくいかない問題にも暫定的に対処している。バグ報告は出したので、そのうちちゃんと直ることを期待している。

その他のInputMethodは「未確定文字列→確定文字列」の順で入力がなされる。一方、SKKの場合は直接確定文字列が入力されるケースがいくつか存在する。(例: ひらかな入力モードにおけるaiueoなど)。 このケースを正常にハンドリングできていないのが原因だと考えられる。

そこで、特定のアプリケーションの場合は、直接確定文字列を挿入するのではなく同様の内容の未確定文字列を直前に挿入するワークアラウンドをいれた。

🐥(\( ⁰⊖⁰)/) face for Apple Watch

suzuki.tdiary.net

に影響されて、Apple Watchの文字盤用の画像を作った。

利用例

f:id:mzp:20150922230143j:plain:w300

ダウンロード

手元に38mmモデルしかないので、42mm版は勘で作っている。 ずれていたら、なんとかしてほしい。

使い方

  1. 上記画像をiPhoneに保存する
  2. お気に入りに設定する
  3. AppleWatchの文字盤切り替えから「写真」を選ぶ
  4. 上記の画像を選択する
  5. (\( ⁰⊖⁰)/)

ライセンス

その他: 開発の流れ

f:id:mzp:20150922231134p:plain

⚡️Brew Sparkling: homebrew for iOS

Xcode7 からApple Developer Programに参加しなくて、iOSアプリの実機デバッグが可能になった。

これを利用し、Github等で公開されているソースコードをダウンロードし、自分のiPhoneにインストールするHomebrew拡張を作った。 例えば brew sparkling install SparkingSample でサンプル用のアプリケーションがインストールされる。

主な用途としては、次のようなアプリケーションの配布を想定している。

  • 進捗時計のような雑なアプリケーション。AppStore審査を通さない分、気軽に公開できるようになる。
  • Provenance(マルチエミュレータ)のようなAppStoreの審査を通過できないアプリケーション。

準備

必要なもの

初期設定

  1. Xcodeを起動し「Preferences -> Accounts」から、AppleIDを登録する。
  2. 右下の「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アプリのインストール

  1. iPhoneMacに接続する
  2. brew sparkling install SparklingSample
  3. 途中でXcodeがKeychainにアクセスしてよいかを聞いてくるので許可する。
  4. 待つ

iPhoneがロックされているとインストールできないので、自動ロックはオフにしておいたほうがよい。

インストールできるアプリケーションの例

Firefox for iOS

f:id:mzp:20150831073641p:plain

Firefox for iOS。現時点ではまだリリースされていないがソースコードが公開されているため、Sparklingでインストールできる。

インストール方法:

brew sparkling install Firefox

JapaneseKeyboardKit

f:id:mzp:20150814222207p:plain

Google日本語入力から派生したMozcをiOSに移植したキーボード。 JapaneseKeyboardKit·Mozcを使ったiOS8用カスタムキーボード MOONGIFTなどで紹介はされているが、AppStoreでは配布されていなかった。

インストール方法:

brew sparkling install JapaneseKeyboardKit

SpoolDays

f:id:mzp:20150814221821p:plain

指定した日付からの経過日を表示するアプリケーション。AppStoreで公開していない理由を作者である@さんに聞いたところ「怠惰」とのこと。

インストール方法:

brew sparkling install SpoolDays

Provenance

f:id:mzp:20150814211833p:plain

SNESSega Genesis、Game Gearなどのマルチエミュレータ。ここでは、スーパーファミコンのプログラムを書きたい - ポルノアニメのROMを動かしている。

インストール方法:

brew sparkling install Provenance

その他

インストール可能なiOSアプリは brew sparkling list で一覧表示できる。もしくはGithubレポジトリを見てもよい。

その他

制限

  • Capabilityが利用できないため、位置情報の取得、バックグラウンド再生、アプリ内課金などの機能は利用できない。
  • 3ヶ月で有効期限が切れるため、定期的に再インストールが必要。

関連リンク

謝辞

Xcodeの挙動を解析するときに@さんにものすごくお世話になったので、Sparklingっぽいものを贈っておいた。

📚Prpr設計判断

🍮 Prpr: bot for github pull requestに、こういう設計にした理由について書くのを忘れていた。

f:id:mzp:20150915222350j:plain

gemプラグイン

gemで動作を追加できるようにするのは当初から計画していた。ただ、まずは一つのgemとして作って後から分割するか、最初から複数のgemとして作るのかは迷った。

結局、最初から複数のgemとして作ることにしたが

  • gemspecを大量に書くのが面倒だった。
  • どこでからがプラグインかが明確になって、クラス設計等がしやくなった。
  • 外部のAPIを叩く部分をすべてプラグインにしたので、本体のspecでモックが不要になった。

といった効果があったので、よい選択だったと思う。

設定ファイル

prpr-checklistなどでは、投稿する文書を設定できるようにする必要があった。ただ、環境変数で設定するようにすると、設定を変更できるのが一部のユーザのみになってしまう。

そこで投稿する内容はレポジトリ内にあるファイルで設定できるようにした。(標準では CONTRIBUTING.md の内容が投稿される。)

一番最初のアイデアではWikiを使うつもりだったが、内容を取得するAPIが見あたらなかったので断念した。

Github限定

プラグインでやりたいことがかなりGithubに依存しそうだったので、対象をGithubに限定した。 レポジトリを操作する抽象レイヤーなどは作らず、プラグインにはOctokitのインタフェースを直接露出している。

対照的にprpr-review_labelの通知先は、特定のサービスに限定していない。これはできることを「テキストの通知」に限定したので、抽象レイヤーを容易に作れたためである。