」って思われたくなかったので、頑張った。いえロジックも実装も雑すぎるので、コードは社内だけの公開に...。発表はハンズオン形式で、全員で一緒にこういうのを作る目標で進めた。classの説明をいい感じにできなかったので、そのあたりから「?」が頭の上に浮かんでる方が出てきてしまい、最後には2名ほど「動かない...」となってしまったのが主な反省点だが、少なくとも僕は楽しかった。Objective-C旧TestFlightがまもなくサービスを終了しますよとメールが届いたので、移行した。そのぐらいにアプリの審査提出が終わってきりが良かったのでささっと。TestFlightへのアップロードにShenzhenを利用していたので、移行先の候補は、このShenzhenが対応しているサービスに絞った。Shenzhen導入時に、これもMatttさん作なことを知り、中村さんがぼそっと「Matttさんって何人居るんだろ...」とおっしゃった場面、今でも思い出して笑ってしまう。有料サービス候補から消えた(理由は言わずもがな...)。Connect)だが、iOS7の対応はまだ切れそうにないのでボツ。Betaしか残らない。AndroidもBetaを使っていたので文句なしで決定した。Betaに変える感じで終わった。思いきや、Shenzhenにipaのファイル名にスペースがあるとファイル名を正しく受け取れないバグがあるらしいので、アップロードは直接Crashlytics.framework内のsubmitを使うことにした。submitにあるオプションも一部対応していないものがあるし、アップロードに関してはあまりShenzhenを使う利点がない。name.”(組織名のすぐ下のリンクをクリックしてね)を見落としてて、API_KEYとBUILD_SECRETを見つけるのに一番苦労した。使い勝手だが、インストールする側の初期設定が、若干TestFlightにめんどくさいのと、アプリのダウンロードがTestFlightに比べ遅いの以外は、ほぼ同じ(もしくはそれ以上)といった印象だ。いちいちアニメーションが凝ってるので、社内での評判も良い感じ?他も含めいろいろお世話になります、Fabric。Extensionの開発などを主に担当した。Extensionも11月頭にほぼ終わったのだがほかもいろいろ盛り込んで審査待っているうちに、今日になってしまった。アプリ開発を内製化して間もないので、いろいろ大変なのだが、こういう対応が遅いのは、少しずつ改善していきたい。Extensionでちゃんと画面から作っているのアプリは国内でもあまりなく、手探りで開発した。Extensionの開発にあたり引っかかったポイントを上げる。ネイティブとは完全に別ターゲットどこでも書いてるから落とし穴ではないが...容量を考えると、共通で使うパーツはフレームワーク化したほうが良い。大掛かりな作業のためSumallyでは諦めてしまった。いつかターゲットの分け方から見直したい。他にもログイン情報やキャッシュファイルを共有するための対応も必要になる。ウェブブラウザからデータを引っ張ってくるサイトで実行するJavaScriptのファイルを指定できる。このJavaScript内でのwindowとブラウザ内でのwindowは完全に別物なことには驚いた。ちなみにSumallyの場合、データを収集するスクリプトを常に最新の状態に保ちたかったので、そのスクリプトをサーバーからロードするJavaScriptをアプリ内に持ち、データが完成次第、ネイティブに渡す実装になっている。DevicesをiPhoneだけにしててもiPadで拡大モードではなく普通に動作してしまう。Layoutで作りましょう。Classesも使いましょう。画面回転の対応をする必要がある様々なアプリがあるので当然のことなんだけど、どこにも書いてなかったので驚いた。Layoutで作りましょう。画面の回転の通知は受け取れないiOS8で画面回転の受け取り方が変わったのだが、開発中いくらやってもだめだった。Layoutでほぼ解決できるけど、横向きでiPhoneの場合だけこうするってのはどうしても出てくるので、SumallyではframeをKVOすることで解決した。UIWindowは使えないアプリ内で使っているインジケータなどは使えない。Lebelがどのあたりだったらいいか分からない。全部UIViewの階層のみで実装した。ポップアップでの表示は自前で実装するiPhoneはポップアップでのUIViewControllerの表示に対応していないので、表示のアニメーションやら閉じるアニメーションやらは自前で実装した。プロダクションのターゲットがある。毎回これらのバージョンナンバーを書き換える作業が面倒だったし、今後どれかだけ変更し忘れるとか起こり得る。ターゲットが増えれば増えるほど、暗くなっていく未来が見えたので、スクリプト化した。ScriptとPython)がある。Gist.実用的なレベルでの初Rubyなので、Ruby業界ルール完全無視になってるかもしれない...xcodeprojとplistをインストールして、いい感じにカスタマイズしてお使いください。FastlaneのActionにあるのでそちらを使った方が良さそうだ。SumallyではFastlaneのを使うようにした。Workいろんなアプリプロトタイプツールがあるけど、Sumallyではいろいろ試し、結局Flintoが一番いいよねって話になった。Flintoはアプリがなく、毎回HipChatからリンクを開いてSafariで開きなおしてSafariでホームスクリーンに追加してようやく起動、とモック表示までの手間が多く、パッと見られないのが唯一の欠点だった。いうことでFlintoのプロジェクトを管理する&表示できるプロジェクトを作った。誰かひとりがFlintoのプロジェクトのURLを登録しさえすれば、あとはみんなのアプリに反映されてアプリ内でモックを確認できる。FlintoはAPIがないので、スクレイピングしてデータを持ってきている。会社に持っていったところ想像以上に好評だったため、オープンソース化した。ホントはサーバー側をもっとちゃんと作ってiOSアプリをストアでリリースできたらいいんだけど、Flintoが仕様を変えたら動かないしAppleの規約に引っかかるのでこれが限界みたいだ...セットアップの方法など、お問い合わせは@chuganzyまで。アップデートも可能性はあるので、その連絡もTwitterでする予定。iOSの画像ロードを高速化しようという話になり、Sumally専用の画像先読みのロジックを組むことになったのだが、completeBlockが呼ばれないので今どれだけプリロードしているかを正しく計測することができなかった。いうことで内部実装を読んでみた。そもそも仕様上ダウンロードをキャンセルした時は呼ばれない昔は呼んでたっぽい実装はちらほら見かけたが、もう完全に呼ばないようになっている。その代わり、キャンセルの時だけNSNotificationCenterにSDWebImageDownloaderOperationがselfをpostNotificationするようになっている(他の時はnilでpostNotificationされる)。それを使ってキャンセルを判別する。Gist.これでもまだ極稀に受け取れないことがある上ので確か解決するはずだったんだけど、デバッグしてると極稀にキャンセルを受け取れてないのがあるっぽかった。こちらは完全にバグ...自信がなかったので、社内用のだけ修正しようと思ったら既にコミットが見つかった。要するに、完了時にblockを辞書から取ってきて消す間に追加されて、すぐさま実行されず消えてしまう可能性があるというバグ。読んで、SDWebImageのイケてない部分が幾つか(結構?)あるっぽいことが分かったし、勉強にもなった。SDWebImagePrefetcherでキャンセルすると表示の方までキャンセルされる昔のバージョンではSDWebImagePrefetcherのダウンロードとUIImageView+WebCacheでのダウンロードの管理は別だったので、二重ダウンロードがされる可能性があったが、どこかのバージョンででそれらが同じマネージャーで管理されるようになり、重複ダウンロードの問題が解決された。これ自体はいいことだけど、弊害として、SDWebImagePrefetcherのcancelPrefetchingを呼ぶと、表示しようとしている部分でもダウンロードがキャンセルになり、結果、画像がところどころ表示されなくなるというバグがあった。そもそもSDWebImagePrefetcherはprefetchURLsをすると、これまでのプリロードをキャンセルする仕組みなのでこの不具合に遭遇する可能性は高い。試行錯誤したので、どう解決したかはヒミツ。2つ目の見出しの件について、SDWebImageにPRを出し(見つけたコミットだとパフォーマンスに影響が出るのと変更し過ぎなので最小限の修正のPR)マージしてもらえた。JavaScriptofxLibwebsocketsのバージョンによっては動くみたい(謎)だが、基本的に接続できない。Socket.ioを使っている場合も同様だ。ローカルでは動くのに...と不思議に思っていて、ローカルとHerokuとの違いを探してもなかなか見つけられず...友人から、「ヘッダの解釈でコケてるみたい」と言われて、他ライブラリでブレークポイント仕掛けてずっと見たら「Sec-WebSocket-Accept」が「Sec-Websocket-Accept」になっててException投げてた。これは気付かない...で、このヘッダを書き直すのにhttpのupgradeでヘッダーを自分で書いても消えてしまうのでサーバー側で解決するのは不可能そう...C++のライブラリを書き直すのもアレだし、一番の解決方法はサーバーを変更することでopenFrameworksの方に手を入れるべきではないと思ったため、とりあえずの対応として、HerokuとローカルサーバーでWebSocket通信をし、ローカルサーバーとoF間でWebSocket通信をするような仕組みで解決した。Gist.それと、Herokuは60秒で接続が切れる。この辺りの実装が素晴らしいSocket.ioを使うことを超おすすめする。上のは切れたらリコネクトしまくる仕組みなので危険だと思った方はいろいろちゃんとやって下さい。HTTPのheaderはcase-insensitiveらしい。いうことで、ofxLibwebsocketsの方を直すべきだ。内部でlibwebsocketsのまだcase-sensitiveだったころの古いやつを使ってるのをどうにかしたらいいと思う(適当)。0.8.4で対応したみたいだ。試していないが上のワークアラウンドは完全に不要になったっぽい。Objective-C結構他のアプリでも、モーダルを複数重ねることは避けられていて(UX的にあまり良くないからもあるんだろうけど)、使っていてもaddChildViewControllerで回避していたりするっぽいので、てっきり一気に閉じることはできないのかと思っていたが、いろいろやってみたらできた。Gist.というか最初からこれだろうと思ってたのだが、なんかの手違いからかできなくて、ワークアラウンド探しの旅から戻ってきて、もう一回やってみたらできたという感じでポカーンとしている。Diary卒業研究がうまく行かず、かなりギリギリまで卒業できるかどうかでヒヤヒヤしていたが、無事大学を卒業できた(今更だけど)。あまりにヒヤヒヤしていたので、大学の思い出の大半がそのときのことになってしまった気がする。3月頭にSumallyに入社したため、卒業式には休みを取り行った。卒業が確定したのが3月中旬より少し前だったので、卒業できてなかったらどうしようという不安でいっぱいだった。卒業研究は、まず、超音波を使ってスマホの位置特定を室内でも超高精度でやろうってことをしてたが、あまりうまく行かず...更にはiBeaconも登場してしまい、同じ概要の技術も特許が取られたり、OSC通信より音速が速くて距離計算出来ない(できるが制限が多過ぎる)しで、もうダメダメだったので12/26に断念。ちなみにiBeaconも試したけど、単純な音の距離減衰を使った場合に限っては超音波の方が余裕で精度は高かった。1月末が論文提出締め切りだったため、そこから大慌てでテーマを変更。年末実家でヒヤヒヤしながら、iPhoneとiPadでの360度どの方向でも見られるビデオ会議システムを作り、年明け大学で評価実験、論文を書いたら、結構余裕で終わった。結局約1ヶ月で終わったことになり、何かずっと無駄な時間過ごした気分だ。RubyPodfileがRubyなので、CoffeeScriptかけるし、ちょろっとRubyを書けるようになっとこうと勉強し始めた。ところがどっこい、なかなか癖があり、1時間でつかめるだろうと思ってたのだが、全くそう簡単にはいかなかった。一応「書け」って言われたら書けるだろうってレベルまでは勉強したが、こういうのはすぐ忘れるのでメモしておく。privateとprotectedうっかり親のprivateをoverrideしてしまったらprivateメソッドにも依存関係が出てしまい消したり出来なくなる。いうことで、内部実装を知らない場合は継承をしない方がよく、委譲を使うのが安全らしい。IntelliJレベルの賢いエディタ使ってたら、回避できそうな問題だけど。ちなみにObjective-Cも同じような問題があるので_からのメソッドは使ったらダメとかなってる。いうか内部実装が見えないケース数で考えるとObjective-Cの方が深刻だな....と::二重コロンといえばC++だとかPHPのクラスのstaticなのにアクセスするときのアレを想像してしまうが...普通にインスタンスへのアクセサみたい。ドットと二重コロンでそこまで違いはないみたいだけど二重コロンは定数へのアクセスも使えるらしい。classやmoduleは定数。==,===,eql?,equal?なんか同じそうなのがたくさんある。いうのが一番困る...まぁ、ざっと見てる感じ==さえちゃんとしてれば使えそうだ。Railsを使いたい人だけ使えばいいと思った。良さは凄く分かるけど。なんだかんだで開発ツール作るときは真っ先にRuby使うようになった。ライブラリの豊富さがすごいしなんとなくで動く。Javaインターンでは初にも関わらずAndroidのアプリ開発のヘルプをしていたのだが、プッシュ通知の実装は結構手間取った。SDKはほんと初めてだった上にJavaは2週間ぐらい授業で勉強した程度だったことから、悩みに悩んだ。Sumallyの場合は開発用と本番用のアプリがあるため、その住み分けなども考えなければならなかった。最初はGCMしか存在を知らず、それで実装していた。実装方法は簡単だったけど、deprecatedとか書いてるし、Androidマニフェストを開発環境と本番用とで書き換えても同じところに取りに行くし(要はライブラリがAndroidマニフェストを見ていない)で、こりゃダメだ...となった。Servicesを使う方法を見つけたので実装。こちらは前者に比べて実装が面倒くさかったけど、ライブラリがしっかりしていた(印象だけど...)ので、開発用と本番用とで悩むことはなかった。Play開発者サービス」とやらをインストール、または更新しないといけなくなる(右のようなアラートが出る)。名前がおかしいし、比較的新しいものなのでほとんどの端末でアラートが出るだろうしで、入れないユーザーが出てきて、プッシュ通知出来ないのは避けたいということに。Play開発者サービスのアプリに対する評価はかなり低い。「なんで勝手に入ってるの?」とかいう人も多く、わざわざ停止させているユーザーもいるようだ。いうことでdeprecatedだけど、従来のGCMを使う方法に戻した。再度、上の問題に突き当たり、悩みに悩んで...Androidマニフェストを参照する(はず)のクラスをextendsして@overrideして何とかした。iOSとは違い、Androidは様々な方法でプッシュ通知を表示できる。いうかPush通知を受け取ったらそれを表示するコードや音を出すとか振動を指せるとかLEDをピカピカさせるとかまでオプションを付けて実装しないといけない。Androidでは、プッシュ通知時のサーバーからの値によって、表示方法を切り替えられたり、振動やLEDをつけたりとできたり、通知の画面から直接ユーザーをフォローできたりという実装をした。今思えば頑張ったなぁ...プッシュ通知。Objective-CopenFrameworksで加速度情報やらジャイロのデータを使って色々しようとなったとき、ofxAccelerometerを使うのが普通と思っていたけど、どうもうまくデータが取れないし、ブラックボックスだしで、そんな複雑なこと考えずに、iOSの場合どうせObjective-C++なのだから、最初からCoreMotionを使った方が楽だと言うことに気付いた。言ったらもうこれ以上何も説明することがないような気がするけど、一応コードを書いておく。CoreMotion.frameworkの追加をお忘れなく。今回はデバイスの姿勢だけだけど、他にも色々取れる。Gist.あとどうやら2つ以上startDeviceMotionUpdatesするともっさりするらしいので、ちゃんと止めるべきときにには止めましょう。Diary一部の方々にはお伝えしたが、実はこの夏、タイトルの通りのことになっていた。ひとつ下の就活が始まったことだし、そろそろ報告しないと...夏休み2ヶ月程、九州のゆっくりした時間の流れの中でぼーっとしたまま社会人になることに不安を感じた僕は、修行を積みに、今日本で最もいけてるサービス運営会社で有名なSumallyのインターンシップに参加した。iOSアプリのバグ修正などなどをした。Androidアプリについては触ったこともなかったのだが、この期間、色々と機能をぶち込んだ。keitapさんの無茶ぶりは毎日冴えており、どんどんタスクが降ってくるもので、僕は、keitapさんが「ヤバイ!もう中元寺くんにやらせることが!ない!」と、困ってるシーンを想像し、目標にして、毎日猛烈にカタカタした。終わりなんてあるはずないのに...まぁでも、お陰様でスキルの伸びっぷりは我ながら凄かったと思う。Hausの2階に呼び出された。インターンで居るだけなのに、呼び出しとなると色々と不安で、「今朝起きるのが遅かったことかな...?」など謝罪文を考えながら、恐る恐る「Androidの引っ張って更新実装できましたよー」とか良いニュースを持って2階へ上がった。そんな予想に反して、結構褒められ、「どうよ?Sumallyで働かない?」と言われ、ポカーンとなったシーンははっきり覚えている。プロダクションへの憧れがあったし、若い内しかできないという考えでいた。そのため「若くて早い時期からプロダクションに参加しないと」と焦っていたのだが、その面談でそれは全然違うことを教えてもらった。