2014年4月30日水曜日

Android で Dagger DI を使いやすくするライブラリを書きました

Daggerというsquare社がオープンソースで提供しているAndroid向けDI (Dependency Injection)フレームワークがあります。


これを試しに自分のAndroidアプリで使ってみようと思い立ったのですが、幾つか問題が発生しました。

  • DI自体の概念が難しい
  • そもそもドキュメントを読んでもDaggerの使い方がよくわからない、公式のサンプルを真似してみても正直いまいちわからない
  • AndroidでDIを行うとなるとandroid.content.Contextの注入が必須になるのだが、Contextは動的なインスタンスであるためDIでの取り扱いが難しい

そこで四苦八苦しながら動くようになったものをライブラリとして公開し、少しでも簡単にDIのメリットだけを享受できればと思いまして DaggeredAndroid なるものを作ってみました。

使い方とかはREADMEを見てください。全部英語ですがすみません(´・_・`)

AndroidでDIを使う際のメリットは主に以下のとおりです。

  • オブジェクトをメンバに接続するだけのコードを無くせるので、コード量が減る。
  • シングルトンの取り扱いが楽になる。
  • Contextの取り扱いが楽になる。
  • Moduleを差し替えればインスタンスが安全に差し替わるので、テスト環境を作ったり、本番と開発環境を分離したりなど、環境の差し替えが楽になる。テスト時のみModuleを上書きすることもできる。

2014年4月20日日曜日

Android の TextView.setText() が遅い場合の原因と対処法

AndroidでTextViewを使っている時に、setText()に数百行単位のテキストを渡すとメインスレッドが1秒弱完全に固まってしまうという現象に見舞われてしまいました。昔の2.3端末ではともかく、手元の最新鋭機Nexus 5 (Android 4.4)でこんなに遅いのでは話になりません。しっかりと原因を調査し対処法を考えることにしました。

まずググってみると出るわ出るわ同じ問題。やはりみんな同じ場所で躓いているようです。
しかしながらいまいち具体的な原因がググっても見つかりません。そこでtraceviewを取ってみました。


すると原因が一発でわかりました。android.graphics.Paint.getTextRunAdvances()です。
Nexus 5では高速化のためJNI経由でネイティブ実装が呼び出されているようですが、それでもまだ間に合わないぐらい遅いようです。それもそのはず、このメソッドは与えられた文字の幅を計算するメソッドです。すなわち数百行のテキストのサイズを計算するため時間がかかっているようです。iOSで例えるならCore TextのCTGryphを計算するようなもの、UILabelのsizeThatFitsを呼び出すようなもので、非常に時間がかかってしまいます。

そこで対処法として、setText()でテキスト全体をセットし直すのではなく、TextViewが裏で保持しているテキストの一部だけを書き換えたり追記したりすることで一度に計算されるテキストのサイズの量を減らして高速化する事を考えました。iOSの場合はUITextViewにはsetText相当のプロパティしか用意されていないので、そのようなことをするのはdelegateを経由してみたりUIKeyInputプロトコルを自前で用意したりなどと困難がつきまとうのですが、Androidの場合は最初からTextViewの裏で保持しているテキストを自在に書きなおすための仕組みが用意されています。

そのためにはまずTextViewの裏で保持されているテキストを「編集モード」にしなければなりません。XMLでandroid:bufferTypeをeditableに指定するか、またはsetText()の第二引数にTextView.BufferType.EDITABLEを指定すると、テキストが編集モードで保持されるようになります。

そうするとgetEditableText()でTextViewが裏側で保持しているテキストが編集可能な状態で取得できます。あとはこのEditableオブジェクトに対して好きなように加工を行うだけです。単にテキストを追加するだけならTextView.append()を実行しても同じ結果が得られます。

こうすると数百行程度であればそれほど遅くなくテキストの追加ができるようになりました。しかしながら1000行を超えてくるとこれでも速度が足りなくなるので、自前でTextViewをサブクラス化して作っていくか、またはListViewにして一度に表示するテキスト量を減らすのが良いと思います。


2014年4月1日火曜日

Objective-🍣


全く新しい、真にユニバーサルな言語へ。


皆さんiOS開発の際にお世話になっているObjective-Cですが、一部の開発者の方々から以下の様な否定的な意見をいただくことがあります。

  • とっつきにくい
  • 文法がキモい
  • @や[]がキモい
  • シグネチャが無駄に長い
  • Apple製品でしか使えない

確かにObjective-Cは習熟すればこれらの欠点を補って余りある素晴らしい言語ですが、これからの更なるモバイルアプリの世界の拡充のためにはより一層多くの開発者に愛される言語になる必要があると私は考えました。

そこでこの度ご紹介するのがObjective-Cをさらに使いやすく、さらに親しまれるように、全く新しく一から作りなおした新言語

Objective-🍣

です!

Objective-🍣とは

以下の様な特徴を持つ言語です!

  • 驚異的に短く、真にユニバーサルな、洗練された文法を持ちます。これまでのプログラミング言語は基本的に英語による記述を強いるものでした。Objective-🍣は真に全人類にとってユニバーサルな絵文字をサポートすることで、この問題をすべて解決しました。Objective-🍣の親しみやすい文法にはすべてのプログラマがシンパシーを感じることができます。
  • Objective-Cと100%のランタイム互換性を持ちます。新しいiOSが登場してもその瞬間からあなたはObjective-🍣の圧倒的なパワーを手にすることができます。

さっそくObjective-🍣で書かれたサンプルコードを見てみましょう!拙作確率計算機のコードをObjective-🍣に書き換えてみました!

before

after

なんというこれまでにない全く新しいソースコード!あのキモかった@や[]、長ったらしいメソッド名がその姿を消しています!そのあまりの美しさには全プログラマが歓喜の涙を流すこと間違いありません!

Objective-🍣の導入方法

こちらのobjsushi.hをあなたのプロジェクト上でincludeするだけで使用できます!簡単ですね!


Objective-🍣を使ってみる

それでは早速ビルドしてみましょう!

あれ

えっちょ

\(^o^)/

ちなみに日本語セレクタ自体はXcode 5以降で普通に使えますよ。

お詫び

こちらの記事にはiOSならびに最新のMacでのみご覧になれる文字(具体的には🍣)を多数含んでおりますことをお詫び申し上げます(´・_・`)

2014年3月20日木曜日

iOSアプリ「確率計算機」をリリースしました


iOSアプリ「確率計算機 (YourLuck)」をリリースしました。
ガチャのドロップ率と試行回数からドロップ期待値を計算するアプリです。
無料です。
https://itunes.apple.com/jp/app/que-lu-ji-suan-ji-gachano/id838156105?mt=8 (JP store)
https://itunes.apple.com/app/id838156105?mt=8 (Universal)

機能

シンプルイズベストなので、以下の2つだけです。

  • 確率計算・・・何回ガチャを回したら、最低でも1個はドロップするか、確率を計算します。
  • 期待値計算(v1.1.0以降)・・・ガチャを指定された回数だけ回すと、一体何個ぐらいはドロップするのか、ドロップする数を計算します。


使い方

特別なことはなにもないのですが、以下のように操作します。



期待値計算モード(v1.1.0以降)

画面左下のこのアイコンを押すと、期待値計算モードに切り替わります。通常の確率計算モードでは「指定された試行回数分だけガチャを回したら最低でも1個はドロップする確率」を表示しますが、期待値計算モードでは「指定された試行回数分だけガチャを回したらだいたい何個ぐらいドロップするか」を瞬時に計算する事ができます。同じモンスターを複数体狙っている時などに便利です。


FAQ

Q: 用語が難しくてよくわからんのだが
A: めっちゃバッサリ言うと以下のとおりです。
  • ドロップ率・・・ガチャのドロップ率です。そのまんまですね。
  • 試行回数・・・何回ガチャを回すかです。
  • 中央にでっかく出る%・・・指定したドロップ率で、指定した回数だけガチャを回したら、100人いるうちここに出ている数字の人が最低1回は指定したドロップ率の何かが出る、という意味です。30%だったら100人のうち30人が最低1回出ます。運がいい人であれば2回以上出るかもしれません。

Q: 絶対確実って表示されてるのに表示されてる試行回数分だけ回しても出なかった!詐欺だ!!!
A: 申し訳ありません(´・_・`) これには幾つか理由があります。
  • 確率は確率なので、例えば98.7%で絶対確実と表示されても1.3%の人、1000人に13人の人は外れてしまいます。これは年末ジャンボ宝くじを1枚だけ買ったら5等3000円が当たった、ぐらいの確率です。すごいのかすごくないのかイマイチわからんですね。
  • 試行回数が多いと誤差が出る可能性があります。具体的には試行回数100回以上はより高速な計算を使っているのですが、そのため精度1~2%程度ですが落ちている可能性があります。

Q: 期待値モードで「最低でも」とか「ほとんどの人は」とか出るけどあれ具体的には何%なの?
A: 以下のとおりです。
  • 最低でも・・・100人中98人がこの数字以上の個数を獲得できます。
  • ほとんどの人は・・・100人中85人がこの数字以上の個数を獲得できます。
  • 半数の人は・・・100人中50人がこの数字以上の個数を獲得できます。

Q: ガチャの確率ってどこで調べればええの?
A: 以下の様な方法をオススメします。
  • ゲーム内に表示されている場合があります。最近のゲームでは特に確率を表示しているものが増えているので、ガチャの画面で注意して探してみてください。
  • グーグルとかヤフーで「ゲーム名 ガチャ 確率」と入力して検索する。
  • 知ってそうな人に聞く。ただしゲームを作ってる中の人とか関係者にTwitterで聞いても絶対に教えてくれないのでそういう人以外に聞いてください。

サポートとか

もし何かございましたら、以下の私の連絡先にまでご連絡ください。
mail: akisutesamaあっとまーくgmail.com
twitter: @akisutesama

2014年3月12日水曜日

iOS SDK 7.1 / Xcode 5.1にアップグレードした時に踏んだ地雷まとめ

本日iOS SDK 7.1 / Xcode 5.1にアップグレードを行った際にぶつかった所々の問題とTipsをまとめておきたいと思います。

arm64対応とCocoaPods

Xcode 5.1からデフォルトのビルド設定$(ARCHS_STANDARD_32_BIT)がarm64、要するに64bit対応を含むようになり、arm64 armv7 armv7sの3つのアーキテクチャに対してビルドを行うようになりました。ソースコードからビルドを行っている場合は大抵問題ないと思うのですが、以下の様なケースでarm64対応を切りたい場合があります。

  • プロジェクト内にarm64アーキテクチャに対応していないstaticライブラリが含まれている場合。
  • 64bitになると危険なバグが発生するおそれがあるコードが含まれている場合、例えばCGFloatやNSIntegerのサイズが変化したり、各種ポインタのサイズが4byteから8byteに増えていたりすると面倒な事が起きるような計算をしている場合。

このような場合、一番簡単な対応策はBuild SettingsのArchitectures(ARCH)をarmv7 armv7sに書き換えることなのですが、こうすると実はCocoaPodsを使用しているプロジェクトの場合リンカエラーが発生してビルドができなくなるという問題があります。
https://github.com/CocoaPods/CocoaPods/issues/1787

そこでBuild SettingsのArchitectures(ARCH)を$(ARCHS_STANDARD_32_BIT)という値に設定すると内部的にarmv7 armv7sとして扱ってくれ、かつCocoaPodsが問題を起こさないようです。この方法をオススメします。この件については以下のページが詳しかったです。
http://stackoverflow.com/questions/8323343/archs-standard-32-bit-vs-armv6-armv7-armv7s-vs-i386

JSONKit対応とCocoaPods

Xcode 5.1からisaポインタへの直接アクセスが完全に禁止になりました。これまでは警告を出さないようにする事が可能でしたが、Xcode 5.1からはそのオプションもなくなり問答無用でビルドエラーにされてしまいます。この問題が最も深刻に出るのはJSONKitライブラリです。
https://github.com/johnezang/JSONKit/issues/79#issuecomment-6322919

対策として一番簡単で確実な方法はJSONKitを使うのを今すぐやめてNSJSONSerializationに乗り換えることです。NSJSONSerializationはiOS 5から使用できるので、あなたが余程のパフォーマンス厨か、またはあなたのプロジェクトが数千万人以上のユーザを抱える巨大プロジェクトで、万一iOS 4系のサポートを止めると何故かあなたの会社ではなく携帯電話会社に「使えないんでなんとかしてください」と苦情が寄せられるような社会的インフラとなったアプリでもなければこの方法を取ることを強くオススメします。

それでも何らかの理由か大人の事情で万一JSONKitをサポートしなければならない場合は、もはやソースコードを書き換えるしか手がありません。幸いにしてXcodeがエラー箇所の修正提案を自動的に全て行ってくれるため、それに従ってコードをホイホイ書き換えれば簡単にビルドが通って使えるようになります。また、すでにそのようなパッチやプルリクエストが山ほどgithub上に用意されています。例えば以下の様なプロジェクトをオススメします。
https://github.com/ignazioc/JSONKit-NoWarning (JSONKit 1.5.2pre, 要するに最新版相当)
http://cocoapods.org/?q=jsonkit-nowarning (CocoaPodsでも使用可能です)

まとめ

CocoaPods爆発しろ

2014年2月25日火曜日

アプリのクラッシュ検知・クラッシュレポート系ライブラリを調べてみた

アプリのクラッシュを検知したり、クラッシュレポートを作成したりするライブラリやサービスを試してみたくなったので色々調べてます。まだ実際に検証できていないので主に自分用メモです。

■なぜクラッシュ検知なのか?

以下の様なメリットが考えられます。
  • アプリのクラッシュを100%絶対完全に阻止する方法は無い。どんなアプリでもクラッシュする可能性がある。
  • 開発者のメリットとして、クラッシュ時に詳細なクラッシュレポートやクラッシュログを数多く収集することができれば、迅速確実な修正が可能になり、結果としてユーザーのメリットに繋がる。
  • ユーザーのメリットとして、クラッシュを検知して即座に編集中データが失われないよう退避したり、次の起動時に同じクラッシュが発生しないようセーフモード起動するなどの措置を開発者が取ることができるかもしれないので、利便性向上につながる。
  • アプリを通じたサービス提供者のメリットとして、カスタマーサポートに飛んでくる何の付加価値もない「動きません」「落ちます」といった苦情を具体的に解決しやすくなり、カスタマーサポート品質を高めたり要員コストを削減したりすることが可能になるかもしれない。
  • ゲームなどでは、例えばクラッシュが発生したら、次の起動時に1つのバージョンに付き1回だけ自動的に詫び石が配られる仕組みなどを作ることができるかもしれない。ゲームのキャラクターにごめんなさい><と謝らせるとなおグッドかもしれない。
逆にデメリットもあって、例えば
  • クラッシュ検知の仕組みが入ることで動作がかえって不安定になるおそれがある。SDK自体が問題を起こすなど。
  • クラッシュ検知の際に対応して行う処理がかえって致命的な問題を起こすリスクもある。exception handlerやsignal handlerを捕まえて検知する仕組みのため、それらを利用している他のSDKなどと競合するおそれがある。
  • 当然それらの機能の分だけ実装とQAと保守のためのコストが上がる。
  • 特にプロプライエタリなサービスのものに関しては会社の方針で導入ができないことがある。
メリデメをよく考えて導入する必要がありそうです。

■サービスとして提供されているもの

以下のページのまとめが詳しいです。
http://www.raywenderlich.com/33669/overview-of-ios-crash-reporting-tools-part-1

Crashlytics
http://try.crashlytics.com

Crittercism
https://www.crittercism.com

Bugsense
https://www.bugsense.com

TestFlight (クラッシュ検知以外の方が有名)
https://www.testflightapp.com

HockeyApp (クラッシュ検知以外の仕組みもある)
http://hockeyapp.net

■オープンソースなもの

KSCrash (iOS)
https://github.com/kstenerud/KSCrash

ACRA (Android)
https://github.com/ACRA/acra

実際に使ってみてまたレポートなど書いてみようと思います。

2014年2月24日月曜日

Google Analytics for iOS SDK バージョン3で自動セッションマネージメントをするライブラリを書きました

Google Analytics for iOS SDK バージョン3にちょっとした機能を追加するライブラリを書いてみましたので公開いたします。

https://github.com/akisute/GAI-AutomaticSessionManagement

iOS 5.0以上で動作します。MITライセンスです。

■これは何?

Google Analytics for iOSは皆さんご存知の通りiOSアプリのセッション解析を行ってくれるSDKです。WebのGoogle Analyticsと同様に、ユーザーさんがどれぐらい、どのように自分のアプリを使ってくれているのかを調査することができます。

そんな便利なGoogle Analyticsなのですが、iOS向けのSDKバージョン3から何故か自動セッションマネージメント機能がなくなってしまいました。すなわちアプリがHomeボタンを押されてバックグラウンドに入ったとしてもセッションが自動的に切れないためセッション数およびセッション時間の正しい計測ができません。iOS SDKバージョン2以前、およびAndroid SDKバージョン3では相変わらず自動セッションマネージメント機能が有効になったままのため、何も考えずにSDKを導入するとAndroidとiOSで大幅に数値が異なるという悲しい事態に陥ります。多分大人の事情なんだろうと思います

ということでこのライブラリを作りました。このライブラリを突っ込めばこれまでどおりアプリがバックグラウンドに入ったら自動的にセッションが切れます。他にも同じように困っている人が居るはずだと思って似たようなことをしている人を探してみたのですが、まったく見つからず困ったので自分で作ることにしました。

インストール方法や使い方などはgithubのリポジトリを見ていただければと思います。

2014年1月18日土曜日

ユビレジを支える技術


年末にユビレジさんのところでちょっと仕事のお手伝いをさせていただいたので、その時の内容をご紹介させていただきます。

■ユビレジって何?

iPadをキャッシュレジスタに変えてしまうサービスです。会計からレシートの印刷までやってくれます。最近飲食店などでレジがなくiPadだけが置いてあるお店などを散見するかと思いますが、アレがそうです。一般的なキャッシュレジスタ+店舗システムよりもはるかに安価で導入でき、しかも使いやすいというのがウリです。

開発者的に言うと、Scalaモヒカン@kmizuさんやiOSモヒカン@k_katsumiさんなどが在籍されていまして、エンジニアのレベルが高いです。

■開発スタイル

少人数のため、厳密なウォーターフォール管理やアジャイル/スクラムなどは無く、チケット/Issueベースの開発になっています。githubをフル活用します。すべてPull Request(以下PR)ベースで開発され、すべてのPRについてレビュー/CI完備です。forkして修正してPRを投げると自動的にJenkinsがテストを回し、githubのPRページに問題なし/問題ありのコメントを投げるところまで自動化されています。正直半端ないです。

完全に裁量労働になっているため、エンジニア勢は猛烈に朝が遅いです。全員が揃うのが普通に昼過ぎだったりします。朝が弱い人でも安心です。

社内コミュニケーションのためにHipChatを使用しています。使用したのは初めてだったのですが、SkypeやIRCよりも以下の様な点で非常に使いやすく魅力的でした。もし機会があれば私もHipChatを導入したいです。

  • IRCと異なり、自分がいない間の過去ログがきちんと残る。
  • Skypeと異なり、APIが公開されているためbotが作りやすい。Jenkinsやgithubとの連携もらくらく。
  • SkypeやIRCと異なり、モバイルアプリの出来が非常に良い。
  • ただし、SkypeやIRCに比べて外部のお客さんを誘うときにちょっと抵抗があるかも。

■サーバサイド

Railsです。私が余りRailsに詳しくないのと殆ど触ってないのでどうすごいのかよくわからなかったのですが、確かRails 3.X系を使用していて、ちょうど4にアップグレードする作業を進めていたかと思います。コードは全PRがレビューされているだけあってものすごい綺麗です。

先述の通りCucumberテスト完備です。
ドキュメントもAPIを外部公開しているので (http://ubiregiinc.github.io/ubiregi-api/) ある程度揃っていますが、完備と言うまでではありません。必要に応じてコードを読めスタイルです。私も結構読みました。というわけでクライアントサイドのエンジニアの方でもある程度以上サーバサイドを理解している必要があります。

フロントエンドまわりの技術については私が係る箇所がなかったためよくわかりませんでした。すみません(´・_・`)

インフラはHerokuを使用してます。デプロイもgithubから一発という仕組みになっています。

■クライアントサイド

ユビレジは現在iPadでのみサービスを展開されているので必然的にクライアントはiOSでiPad向けのみとなっています。ここだけ聞くとiOS/Android両対応だのハンドセット/タブレット両対応だのが必要ないため簡単そうに思えますが、そんなことは全くありません。お客さんがお金を払ってサービスを導入するB2Bアプリで、かつレジという会計を扱うアプリであるため並大抵の無料B2Cアプリとは比較にならないレベルで不具合が許されません。さらに注文を取るハンディ機などの外部アプリ連携、レシートプリンタなどの外部ハードウェア連携、サーバとの会計情報同期、iOS 5&初代iPad対応などが要求され、会計回数も大規模なお店だとそれなりの件数に達するためCore Dataもパフォーマンス最適化が必要になるなど、実はそれなりに難易度が高いです。iOS 7にiPadでのみ発生する問題が多いのも逆風ですね。

まずModel層について、データストアはCore Data+自作の薄いラッパです。MagicalRecordはちょっと複雑で大規模すぎるため導入していないとのことです。通信周りは普通にAFNetworking (1.X系)を使用。2.X系は今後iOS 5を切ってから導入する流れになるのではないかなとのことです。

View層についてはほぼすべてStoryboard/xib化されていますし、Segueもバリバリ使います。シンプルなUIが多いため派手派手なUIライブラリはほとんど使用していませんが、広い画面を有効に使う必要があるiPadアプリならではとして、Container View Controllerの概念をよく使うことになっています。

ちょっと変わっているのが、ビジネス用途で使うためSingle App Modeを有効にしてユーザーがホームボタンを押してもユビレジアプリから外に出られないように設定するのですが、この設定を有効にした時にモーダルなView Controllerを出すと問題が生じる場合があるのでワークアラウンドを導入していたりなどします。こういう問題は普通のB2Cアプリを作っているとほぼ気づかないので大変です。

それからユビレジ特有の問題としてハードウェア連携周りが挙げられます。このへんはは完全に自作です。Raspberry Piを使った自社ハードウェアとWiFi経由でデータをやりとりする仕組みになっています。普通のプロダクトではこういう開発が出来る場所は殆どないので貴重な体験になりました。

サーバサイドにもありますが、クライアントサイドにもfrankを利用した受け入れテストがある程度用意されていて、こちらもPR時に自動的に走るという仕組みになっています。ただしちょうど私が参加したのが次のアプリの大改修に備えていた時期だったため、テストの整備が追いついていない感じでした。

■まとめ

非常に短い期間だったのですが、エンジニアが一度は夢見る理想的な環境みたいなのをある程度実現されているのが素晴らしいと思いました。もちろん完璧というわけではなく今後も維持改善が必要なところがありますが、このような理想環境を一度体験してみたいというエンジニアの方には非常に魅力的な場所だと思います。

現在ユビレジさんはエンジニアの方を募集されているそうなので、興味を持たれた方は一度オフィスまで遊びに行ってみてはいかがでしょうか?

2014年1月12日日曜日

iOS 開発者が Android 開発者になるために用意したものまとめ


これまでiOS 2.0の登場から今日に至るまでiOS開発者として仕事してきたわけですが、今年はいよいよ本格的に仕事でAndroidの開発を行っていきたいと思っています。そこで正月休みを使って準備したAndroidの開発環境や勉強用の資料をまとめてみました。同じく今年からAndroidやってみよう!という方の助けになればと思います。

■前提条件

まず最初に前提条件として筆者のスペックをまとめてみました。
  • iOS開発歴4年ぐらい (iOS 2~7)
  • Android開発歴半年ぐらい (Android 1.5~2.1の間、仕事では殆ど使ってない)
  • Java歴は3年ぐらい (大学時代と最初の会社でSIerをやっていた間、SJC-P所持だがJava 7とか8とかはわからない)
iOSの開発歴が長く、モバイル開発で必要な要素や落とし穴などをひと通り踏んでいること、少しですがAndroid開発歴があること、Javaについてもひと通りの文法がわかるのを前提としています。従いまして完全にモバイル開発もJavaも初めてという方にはおそらく今回の資料は少しハードルが高過ぎると思います。ご了承ください。

特にJavaについてはどの資料も何の説明もなしに匿名クラスや内部クラスをふんだんに利用するので、最低限Javaの事前勉強をしておいたほうが良いかと思います。

■開発環境の用意

今回はMac上にAndroid Studioをインストールする方針でいきます。
http://developer.android.com/sdk/installing/studio.html
Eclipse+ADTな現場もまだまだ多いかと思いますが、今後は間違いなくAndroid Studioが主流になってくると思われるからです。あとは個人的にEclipseが嫌いというのもあります(´・_・`)

インストール時の注意点としては初回起動時に少々時間がかかるのと、アップデートが必要になる程度です。0.3.2から0.4にアップデートする前にプロジェクトを作ってしまうとアップデート後にビルドが通らなくなってしまったので、最初にまずアップデートすることをオススメします。

Android StudioではEclipse+ADTの環境や、旧来のJava開発とは異なりGradleというビルドツールが何をするにも主体となります。そのためGradleについてある程度の知識が必要となります。幸いにしてWeb上に良い記事がありましたのでこちらを参考に勉強しました。

■シミュレータの用意(Genymotion)

ADTには最初からAndroidエミュレータが付属されていますが、これは残念ながらiOSのシミュレータとは異なり、再現度も悪く異常に動作が遅いため使い物になるシロモノではありません。Android SDK 1.6のころから現在4.4に至るまで全く改善の気配が無いため、おそらく未来永劫改善は望まれないと思われます。その代わりと言ってはなんですがGenymotionというサードパーティ製の非常に使い勝手の良いAndroidシミュレータがありますのでこちらをインストールします。
http://www.genymotion.com

アカウントを作成してFree版をダウンロード・インストールします。Free版と有料版の違いは加速度センサーのエミュレーションや、スクリーンキャスト機能の有無程度なので、Free版でまったく問題ありません。Genymotionの起動にはOracle VirtualBoxが必要になるため、https://www.virtualbox.orgからダウンロードしてインストールしておきます。

最後にAndroid StudioのGenymotionプラグインをPreferences -> Plugins -> Brows RepositoryからGenymotionで検索してインストールして完了です。

■開発機の用意

Genymotionだけでもかなりの開発はできますが、やはりモバイル開発では実機上での確認が必須です。特にAndroidはiOSと異なり端末種類が多い上に端末差異が激しいので、出来る限り多くの実機を用意しておくことが望ましいです。またそれだけではなく、実際に日常生活でAndroidを触り多数のアプリに触れておくことで、Android上でのアプリの作法や最近の流行、iOSとの違いなどを肌で学ぶことができます。

開発用の端末は白ロム(中古品)販売店で安く買うのが良いと思います。通販でも購入可能です。
http://masterka.seesaa.net/article/252845343.html

ですが今回は折角なので最新機種Nexus 5をGoogleから直接購入することにしました。
こちらから直接SIMロックフリーのNexus 5を通販することができます。私の場合は1/1に16GB Whiteを注文して1/5に届きました。正月でなければもうちょっと早かったかもしれません。

届いたら開封して起動すればそのまますぐに使えます。iPhoneと異なりSIMがアクティベーションに必要だとか、iTunesと接続を要求するとかそういう内容は一切ありませんので、SIMを購入しなくても開発機として使用可能なのがいい感じです。ただし最初の言語選択とWiFi接続時のエラーメッセージが非常に不親切なのでちょっとハマりました。

Nexus 5を使ってみての感想ですが、正直信じられないぐらい良いです。Android 2.x時代のダメダメ端末ばかり触っていたのでギャップが大きいというのも有りますが、電池の消耗がiPhoneと比べると激しい以外は欠点らしい欠点が見当たりませんし、余計なものが一切入っていないのでAndroidの長所を存分に味わう事ができます。iOS開発者の人でAndroid開発に手を出したい人にはまずオススメしたいです。

そのままSIMなしで開発機として使っても良かったのですが、3G回線でのテストも行いたかったので、今回はさらにMVMO業者のSIMパッケージを購入しました。初期費用3000円、月額1000円以下、二年縛り無しでSIMが手に入るため非常に安価で便利です。
などがありますが、今回はOCN モバイル Oneを選択しました。

■Hello World!

さて開発環境も開発機も手に入ったので、あとはコードを書くだけです。最初はまず以下のWebサイトを参考資料に簡単なTwitterクライアントアプリを書いてみました。
やはりモバイルアプリ開発の手習いはTwitterクライアントアプリからスタートするのが良いと思います。データのリスト表示、非同期通信、画像の非同期読み込みとUIへの反映、一覧と詳細表示など、モバイルアプリに必要な要素がバランスよく学べます。

■購入した書籍

Webの資料も悪くないですが、やはり最初は書籍を読みながら進めるのが情報がまとまっていて近道だと思います。というわけで以下の書籍を購入しました。すべて達人出版会の電子書籍で手に入るため便利です。
  • Google Androidプログラミング入門改訂2版: http://tatsu-zine.com/books/androidprogramming2ed
    • 入門に必要な内容はひと通り網羅されていると思います。ただし入門書を名乗っていますが、途中からサンプルプログラムが手元にあること前提の説明になったり、コードの一部が説明されていなかったり、Javaがわかること前提のコードが登場したりなど難易度が急激に跳ね上がるので、本当の本当に入門な人には向かないと思います。
  • Effective Android: http://tatsu-zine.com/books/effective-android
    • Effective系は外れないと思って購入しました。Effective Javaも名著でしたしね。
  • Android UI Cookbook for 4.0 ICS(Ice Cream Sandwich)アプリ開発術: http://tatsu-zine.com/books/androiduicookbook40
    • 4.0でUI周りは大きく変わっているので、2.3との互換性維持のノウハウも含めて欲しかったので購入しました。iOSの手習いの時もObjective-Cの本とUIKitの本を選びましたが、最初は言語の本とUIフレームワークの本を選ぶのが良いと思います。
  • Android Security 安全なアプリケーションを作成するために: http://tatsu-zine.com/books/androidsec
    • 仕事でAndroidを使うつもりなのでセキュリティ周りの情報は必須です。セキュリティに関してはiOSよりも更に環境がシビアですので、念には念を入れておきたいです。


2014年1月7日火曜日

LLDB のカスタムコマンドを Python で書いてみようとして大失敗した話

なんかうまくいかないんです(´・_・`)

Xcode 5のデバッガとして用意されているLLDBですが、実は設定ファイルを書くことで自由にカスタマイズすることが可能になっています。またPythonを使ってより深いLLDB自体の挙動をカスタマイズすることも出来るらしいと最近教えてもらいました。

参考: http://qiita.com/dealforest/items/e3a5284badd17733ccc1

さてこちらの参考記事に、
例えば動的に生成した UIImage をファイルに出力するコマンドとかは便利そうですね。
というなかなか夢のある発言があるのですが、残念ながらこちらの記事の中では実際のコードがありません。ということでLLDBの設定の練習がてら、私の方で早速デバッガからUIImageをファイルに書き出すコマンドの作成にチャレンジしてみました。

■実装方針

LLDBを操作するために使用できるPythonモジュールについては、LLDBの公式ページに詳しいドキュメントが揃っています。
http://lldb.llvm.org/python-reference.html (簡単な解説とチュートリアル)
http://lldb.llvm.org/python_reference/ (APIドキュメント)

また既に何人かの方が似たようなことをされた形跡があります。
http://stackoverflow.com/questions/12668815/lldb-python-access-of-ios-variables
http://stackoverflow.com/questions/18468126/pointer-arithmetic-in-lldb-python-scripts
http://lists.cs.uiuc.edu/pipermail/lldb-dev/2011-January/000321.html

これを元にして、以下の様な戦略でいってみます。

  1. 引数のUIImageをUIImagePNGRepresentation関数を通してNSDataにする。
    • ただのUIImageをそのままファイルに書き出しても使えませんので、まず一旦JPEGなりPNGなりに変換する必要があります。ここではObjective-C側に変換してもらうことにします。
  2. NSData bytesを取得する。
    • expr (const void *)[(NSData *)UIImagePNGRepresentation(image) bytes]とか叩けば一発なはずなので、その方針で行きます。
  3. ファイルに書き出す。
    • exprの結果をraw dataで取り出せれば、あとは普通にファイルに書き出しておしまいです。簡単そうですね。
ということで出来たコードはこちら。


■しかし

やはりというか落とし穴がorz
冒頭の画像にもあるのですが、Python経由でexprした実行結果を取得する手段がどうにも見つかりません。SBFrame.EvaluateExpression(expr)の結果がSBValueなんだからそっからデータが引けるだろうと思っていたのですが、何を実行しても壊れたSBValueしか返却されないためどうにもうまくいきません。SBDebuggerやSBCommandInterpreter経由でHandleCommand(expr, result)する手も考えたのですが、今度はresultから値を取る手段がない(resultをコンソールではなくファイルにリダイレクトする手段しか無い)ためやはり断念です・・・

うーん。もう少し頑張ったらうまくいきそうな気もするのですが。残念です><


2014年1月6日月曜日

Spark Inspectorを一ヶ月ほど使ってみた感想


ちょっと仕事で複雑なiOSの画面を作りたいということになり、デバッグに難儀していた所、Spark InspectorというiOS向けのランタイムインスペクタツールが発売されていましたので、やや乗り遅れた感がありますが私も早速試してみました。

Spark Inspectorを使うと、

  • リアルタイムにViewの構造を視覚的に確認し、直接プロパティの値を編集してアプリに反映させることができる
    • Webエンジニアの人にわかりやすくたとえるならば、ChromeやFirefoxなどに付いているインスペクタをiOS上で使えるようなものです
  • その他、アプリ内を飛び交っているNSNotificationの状態を監視することができる(らしい)

既に試された方のブログ記事で導入方法など詳しく公開されていますので、まずはそちらを見ていただくのが良いかと思います。
Spark Inspectorを導入してみた
http://inon29.hateblo.jp/entry/2013/12/06/002948
[Xcode][tool] ランタイムデバッガーSpark Inspectorが便利!
http://blog.natsuapps.com/2013/05/spark-inspector.html
ということで、私は一ヶ月ほど実際に仕事で使ってみて良かった点と悪かった点をまとめてみようかと思います。興味ある方の参考になればと思います。

■良かった点

導入が非常に楽です。ブログ記事で既に紹介されている方法は自分のプロジェクトに必要なフレームワークを組み込んで設定する方法ですが、最近のSpark Inspectorはこの方法を用いなくてもXcodeから一発で必要なフレームワークを動的に読み込んでインスペクタを起動してくれます。

Viewの階層構造をリアルタイムに監視できるのはやはり非常に有効です。これまではUIView- (void)recursiveDescriptionプライベートメソッドを呼び出したりして状態を確認したりしていたのですが、実行中の画面に対して動的に状態を見て、動的にプロパティの値を書き換えて見た目を調整することができるのは劇的に作業効率を改善してくれます。これってWebプログラミングだと実に当たり前のことなんですが、iOSプログラミングだと余りまだ普及してない考えだなと思います。

動作はやや重いですが、2012年モデルのMacBook Airでも問題なく動作させることが出来ました。もちろんiPadのアプリでもちゃんと動作します。

■イマイチだった点

楽に導入できる、自分のプロジェクトに必要なフレームワークを組み込まないやり方では、いくつか制限があります。

  • 自分のプロジェクトに必要なフレームワークを組み込まないと、実機でSpark Inspectorを動作させることが出来ない。
  • 動作が非常に安定しない。プロジェクトによってはかなりの確率で起動に失敗したりする。今回私が仕事で使っていたプロジェクトでは8割ぐらいの確率で起動に失敗していた。

それから地味に痛いのが、表示と編集が可能なのが現状CALayerとUIViewのプロパティのみに制限されているところです。Auto Layoutには対応していませんし、例えばUIScrollViewのcontentInsetを動的に調整してみたりですとかUIButtonの横幅とタイトルを動的に調整してみたりですとかそういう小技が出来ないため、なんというかかなり中途半端感を受けます。結局私の場合は表示されているはずなのに表示されていないViewの構造を調べる程度の用途にとどまりました。

2013年12月14日土曜日

Webページのサムネイル画像を生成して表示する AKWebRenderer を公開してみました


Social.frameworkSLComposeViewControllerに貼り付けたURLのWebページのサムネイル画像を表示する機能があるのですが、それを真似する感じのライブラリです。TwitterのTLをダラダラ見ていて画像とURLをダラダラ流すだけのTwitterクライアントを作ってみたら面白くないかなと思ってやってみました。

リポジトリはこちらになります。
https://github.com/akisute/AKWebRenderer

使い方やライセンスなど全てREADMEに記載しておきましたのでそちらをご覧ください。

注意点として、遅い・重い・不安定の三重苦です>< 実用で似たようなことをしたいのであればサーバを自前で用意して事前に画像をレンダリングさせるほうが良いと思いますが、SLComposeViewControllerと同じような動作がさせたいだけならばそこそこ使えるんじゃないのかと思っています。一応キャッシュとかもついてます。

2013年12月9日月曜日

Xcode 5 で、発生した NSException の詳細が表示されない時の対処法

原因がよくわからないのですが、iOSアプリをデバッグ中にNSExceptionが発生してアプリがクラッシュしてしまった時、その詳細がXcodeのコンソール上に表示されなくなってしまいました。普通はデフォルトのexception handlerがうまい具合にやってくれるのですが、何らかの理由でそれがうまくいかない場合があるようです。自分でスレッド立ててるとかでしょうか・・・


上図のように、例外が発生している箇所にブレークポイントをおいてどこで発生したのかを知ることはできるのですが、実際には発生箇所がわかっても発生原因がさっぱりわからないというケースもあります。例えばiOSのシステムが例外を発生させたときや、コードが公開されていないライブラリが例外を発生させたときなどです。

さて、このようなときは発生しているNSExceptionのdescriptionを直接読めれば便利そうです。というわけで調べてみました。

http://stackoverflow.com/questions/384775/how-do-i-find-out-what-exception-was-thrown-in-the-xcode-debugger-for-iphone
After you stop in the debugger, you can enter po $eax (simulator) or po $r0 (device) to see the exception. This is because the exception object is passed as the first argument to objc_exception_throw, which is kept in register r0 or EAX.
こちらの投稿のコメントにちょっとだけ書かれている方法がどうやら一番良さそうです。というわけで試してみました。
  1. まずはプロジェクトのAll Exception Breakpointを有効にします。
  2. アプリをデバッグして、例外が発生する箇所を実行します。
  3. 例外発生箇所でブレークポイントが発動したら、左のスタックトレースナビゲーションから、スタックトレースの一番上(objc_exception_throw)を選択します。
  4. コンソール上で以下のコマンドを実行します。
    • シミュレータなら、po $eax
    • 実機上なら、po $r0
うまくいきました!これで万一発生した例外の原因がよくわからない場合でも安心です。

余談ですが、eaxレジスタ/r0レジスタは関数の引数だかなんだかに相当するレジスタみたいなので、よくわからないコードで詰まっている場合はここを見れば他のケースでも解決できるかもしれません。

2013年11月27日水曜日

Mac の Skype のデータベースを最適化してパフォーマンスを向上させる小技



もりよしさんにSkypeで教えてもらったのですが、Mac版のSkypeクライアントってデータベースにsqlite3を使用しているんですね。少なくとも3年前には既に知られているネタみたいなのですが、ぜんぜん知りませんでした。
http://d.hatena.ne.jp/shishimaruby/20101214/1292288183

というわけで、Mac版のSkypeをお使いの方は
~/Library/Application Support/Skype/(自分のアカウント名)/
以下にsqlite3のデータベースファイルがあるので、Skypeを一度終了した状態で
sqlite3 main.db VACUUM
sqlite3 main.db REINDEX
という感じでVACUUMREINDEXを実行すると劇的にパフォーマンスが改善します。特に仕事とかで大量のログを見ている方におすすめです。私の場合、370MBもあったログが270MBまで減って、Skypeの起動も高速化しました。

※注意: このコマンドはSkypeのログデータベースを直接操作します。最悪全てのログが失われる危険があります。何を言っているのか分からない、ターミナルの操作なんて知らないという人は実行しないことを強くおすすめします。

Unity の PostprocessBuildPlayer を Ruby で書いてみる(第二版)

UnityでiOSのアプリを作っていて困ることの一つに、iOSが提供するシステムフレームワークへのリンクをプロジェクトに追加するのが超面倒くさいという問題が挙げられます。UnityがiOSアプリを書きだした後、手動でXcode上からシステムフレームワークを追加してもいいのですが、これはとんでもなく面倒です。というわけで、以前こちらの記事でRubyのxcodeprojモジュールを利用して自動的にシステムフレームワークを追加する方法をご紹介しました。
http://akisute.com/2012/09/unity-postprocessbuildplayer-weak.html

今回はそのPostprocessBuildPlayerをさらに機能拡充しましたのでご紹介いたします。主な機能として、
  • システムフレームワークへのリンクをプロジェクトに追加する
    • dylib, framework両方に対応
    • required, optional両方に対応
  • 空のinfo.plistをプロジェクトに追加する
    • ja, enに対応
    • Unity 3時代に空のinfo.plistを追加しないとiOSが提供するUIが英語で表示される問題が合ったため追加
    • Unity 4以上であれば修正されているかも
  • ヘッダサーチパスをライブラリサーチパスからコピーして自動設定する
    • Unity 3時代にビルドにこける事があったので追加
    • Unity 4以上であれば修正されているかも
  • ローンチイメージを自動設定する
    • 容量の関係で極限まで圧縮したjpgをpngの代わりに使いたいということで追加
    • 現在のXcode 5/iOS7向けの環境ではjpgを利用したDefault.pngは全く考慮されていない用に見えるので、使わないほうが無難だと思います
  • main.mmの書き換え
    • ここではSystem.Net.Socket.SocketがSIGPIPEを飛ばしてアプリ全体をクラッシュさせてしまうことがある問題を回避するためにsignalを捕まえたりしています
    • 変更規模が大きいならわざわざここでやるよりUnity側の/Assets/Plugins/iOSにmain.mmを置くほうが良いかと思いますが、ちょっと書き換えるだけなら有用です
  • AppController.mmの書き換え
    • 変更規模が大きいならわざわざここでやるよりUnity側の/Assets/Plugins/iOSにAppController.mmを置くほうが良いかと思いますが、ちょっと書き換えるだけなら有用です
インストール方法は、
  • まずソースコードを取ってきてPostprocessBuildPlayerという名前でUnityプロジェクトの/Assets/Editor/以下に配置します。
  • 実行にはRubyとバージョン0.4.xのxcodeprojモジュールが必要になりますので、インストールします。より大きいバージョンのxcodeprojでは動作未確認ですので、0.4.x系を指定することをおすすめします。
    • sudo gem install xcodeproj --version '~>0.4.0'

ソースコードはこちらになります。MITライセンスです。

余談になりますが、最近ではRubyのxcodeprojを使うのではなく、Pythonのmod-pbxprojを使う方法もあるみたいです。@Seasons氏はこちらの方法を使われているそうです。Pythonのがいい!という方はいかがでしょうか。



2013年11月3日日曜日

Objective-Cでパターンマッチしたい

また誰得な妄想ネタですみません><

突然ですが、Objective-Cでパターンマッチがやりたいんです。MLだとかOCamlだとかScalaだとかみたいに。
MLの例: http://kktoppa.web.fc2.com/smlnj4.html
OCamlの例: http://www.geocities.jp/m_hiroi/func/ocaml04.html

パターンマッチがないせいで、StoryboardでSegueを使ったとき、こんな何かの冗談みたいなコードを書かなくちゃいけないんです。

見ての通り、大学時代に恩師が「アホのn段重ね」と読んでいたif~elseの重ね技です。これ以外に方法がないんです。

だからこういうコードが書きたいんです。厳密には関数型言語のパターンマッチと違う気がしますしなんか色々とメチャクチャな文法になってますが、だいたいなんかこんな感じのコードが。

しかし残念ながらObjective-C (CでもC++でもいいですけど) の文法を捻じ曲げるのは極めて難しいです。

Rubyならこんな感じでパターンマッチを実現するライブラリがあるみたいです。素敵ですね。
http://www.callcc.net/diary/20120303.html
https://github.com/k-tsj/pattern-match

というわけで今日もアホのn段重ねでSegueを使おうと思います\(^o^)/

2013年10月30日水曜日

【誰得】ncursesをiOS 7向けにビルドしてみた



久々のブログ投稿がこんな内容でほんとすみません。

ややタイトル出落ち感がありますが、ncursesをiOS向けにビルドしてみました。環境は以下のとおりです。

  • OS X 10.8.5 (Mountain Lion)
  • Xcode 5.0 & iOS SDK 7.0
  • ncurses-5.9
  • TerminalにはOS X付属のTerminal.appを使用

※注意: 本当に使えるかどうかまでは試してません。ちょっと根性が足りませんでした。あくまでiOS向けにC/C++で書かれたライブラリをビルドして使えるようにするときの参考になったりならなかったり程度でお考えください。

というわけで、まずはncursesのソースコードをhttp://ftp.gnu.org/gnu/ncurses/あたりからサクッと拾ってきます。今回はncurses-5.9を使用しましたがどのバージョンでも大して変わらないと思います。

あとはconfigureしてmakeすればOKですが、configureが少々厄介です。そのままだとerror: Cross-build requires two compilers.とか言われてしまいますので、./configureの当該箇所をコメントアウトしてからオプションを付けて実行してください。それから./configureを実行した端末エミュレータ向けにビルドされてしまうようで、その挙動を変更するオプションが見つからなかったのでこちらも注意してください。私は今回xterm向けにビルドしてしまいましたがxtermエミュレータが用意できない場合はVT100などに変更した上でビルドしたほうが良いかと思います。



うまくいけば無事ビルドが通ってタイトルの画像のようになります。
CFLAGSでarchとisysrootを指定してビルドする手法は他のautoconfを使っているオープンソースのライブラリでも応用できそうですね。

さてlibncurses.aはビルドできたのですが、このままでは端末エミュレータがなくてどうにもならないので、iOS用の端末エミュレータを用意しなければなりません。幸いにしてオープンソースのmobileterminalというプロジェクトを見つけましたので、こちらをお借りしましょう。ライセンスがGPLですがどうせこんな酔狂なものを人様の前に晒すことは決してないはずなので問題ありません。

あとはhttp://www.kis-lab.com/serikashiki/man/ncurses.htmlでも参考にncursesでのCUIプログラミングをお楽しみください。多分、きっと、運が良ければ、動くと思います。


参考文献:
http://d.hatena.ne.jp/maminus/20100129/1264781242 - configureのbuild、host、targetの違い
https://twitter.com/moriyoshit - @moriyoshi

2013年5月15日水曜日

「モバイルアプリのバックエンド(Web API)に特化したサービスのまとめ」のその後(2013年版)

1年ほど前にモバイルアプリのバックエンド(Web API)に特化したサービスのまとめというBaaSサービスについて非常に丁寧にまとめた記事が公開されていたのをつい最近知ったのですが、公開から1年が経ちBaaSサービス周りも統合再編が起きているようなので誠に勝手ながら2013年版を引き継いて書いてみようかと思います。

まずBaaSについて基本的なところはlaisoさんの元記事が素晴らしく良くまとめてくださっていますのでそちらを参照してください。

2013/05/16追記: こちらのSlideshareにも2013年現在のBaaSサービスを取り巻く状況が非常に丁寧にまとめられていますので、オススメです。

2013年のトレンド

まずは元記事で上がっていたBaaSサービスの名前を片っ端からGoogleトレンドに突っ込んでみて人気度を評価してみました。その他、2013年になって登場してきたサービスがないか調べてみました。

その結果、はっきりと人気がある勢と人気がない勢が分かれました。

人気がある勢

StackMob
https://www.stackmob.com
実際に使ってみたわけではないのですが、多機能さが目につきます。元記事で言われていたサンプルが動作しないなども直っているようです。しかしながらクラウド側コードをJava/Scalaという結構ガッツリ系言語で書く必要があったりして、お手軽さがParse.comなどと比べて今ひとつ、売りの機能面では最近赤丸急上昇のKinveyに遅れを取っている印象があります。
機能一覧はこちらから。

Parse.com
http://www.parse.com
最近Facebookに買収された、BaaS分野では一番の知名度を誇ると思われるサービスです。以前に実際に使ってみた時の感想など書いてみましたが、ドキュメントとクライアントSDKが極めて充実しており、導入が非常に簡単なのが良いところだと思います。まず困ったら比較基準元としてとりあえず使っておけるサービスとしてオススメできます。
反面、お手軽なぶん機能面では外のサービスに及ばない箇所が見受けられます。特に既存データとの接続が直接的にはサポートされていなかったりするため、エンタープライズ系のサービスには向かないと思います。
機能一覧はこちらこちらが参考になるかと思います。

Kinvey
http://www.kinvey.com
最近トレンドサーチで赤丸急上昇なサービスです。路線としてはStackMobのような多機能でエンタープライズ系も狙えるような路線になっていますが、見た感じクラウド側コードもJSで比較的お手軽に書けるのがいいですね。iOSのSDKだけを見れば、Core Dataのサポートがあったり、NSNotificationで状態通知を飛ばしていたりするなど何かと多機能で嬉しいです。課金がAPI呼び出し数ではなくアクティブユーザー数単位だったりするのもユニークなところです。
機能一覧はこちらこちら、またはこちら

Appcelerator Cloud (元Cloudfish)
http://www.appcelerator.com/cloud/
CloudfishがTitaniumの開発元であるAppceleratorに買収・統合されました。Titaniumを使っている人は事実上全員がターゲット層になりますし、根強い人気が今後も期待できそうです。

人気がない勢

CloudMine
https://cloudmine.me/
ちょっとドキュメントを見てみただけでダメそう感が伝わってくるのがなんとも。

Buddy
http://buddy.com/
どうもクラウド側コードを走らせる機能が無さそうです。イマイチ。ゲームAPIなどが最初から用意されているのですが、内容を見ても(少なくとも日本では)余り使える内容に見えません。

QuickBlox
http://quickblox.com/
LocationやVideo Chat、Content RankingなどのB2Cアプリ向けのサービスが標準提供されており、そういう用途だと良いかもしれません。

yorAPI
http://www.yorapi.com/
サイト自体が潰れてます。

新しく登場した勢

BaasBox
http://www.baasbox.com/
完全にオープンソースなのが売りみたいです。ScalaのPlay!フレームワーク上に実装されており、自分でJVMの動作するサーバを用意すれば環境を構築することができます。弱点は機能がまだほぼ皆無でクライアントSDKもまったくないことです。要するにまだ全然使えません。一応クライアントSDKはリリース予定があるみたいです。

appiaries
http://www.appiaries.com/jp/index.html
ついに登場した日本のBaaSサービスです。が、残念ながら現地点では機能が大きく人気のある勢に対して劣っており、クライアントSDKもクラウド側コードもどうやらまだ存在しないようです。現段階ではオススメしづらいですが、今後どうなるか次第ですね。

Kii
2013/05/16追加
http://www.kii.com/
もう一つの日本のBaaSサービスです。appiariesよりも完成度が高くParseにサービス内容と料金体系が似ています。iOS/Android向けのクライアントSDKもきちんと用意されていますが、クラウド側コードはまだ準備中になっており使用出来ませんでした。特徴的な点としてアドネットワークとの連携が標準で用意されていたり、ファイルストレージにゴミ箱機能や共有機能があったりします。実際には試せていないのですが、サーバが日本にあるため応答性が良いかもしれません。
機能一覧はこちらこちらこちらのスライドも非常によくまとめられていてわかりやすいです。

Windows Azure Mobile Services
2013/05/16追加
https://www.windowsazure.com/en-us/develop/mobile/
Microsoftが提供しているWindows AzureクラウドのMobile向けサービスです。クライアントSDKもWindows/Android/iOSに対応済み、クラウド側コードをJSで記述可能、さらにはcronに相当するクラウド側コードの定期実行も可能と、こういったところはさすがのMicrosoftという印象を受けます。ただしクライアントSDKはWindows向けのもの以外開発途中でドキュメントも貧弱、サービス内容もそれほど充実していません。Windows Azure自体との連携もあると思われますが、詳細がよくわかりませんでした。

2013年5月2日木曜日

Parse.com の Cloud Code ハマりどころ

Parse.comのCloud Codeを触っていてハマった点や気づきにくい仕様を列挙させて頂きます。

■Parse.Cloud.useMasterKeyを呼び出すことで特権ユーザー権限になれる

Cloud Code上でACLによるアクセス制限を無視して現在のrequest.userとは関係なしにデータを操作したいということが多々あるかと思います。そのような場合は以下のようにリクエスト処理の先頭でParse.Cloud.useMasterKeyメソッドを呼び出してください。

useMasterKeyの効果は呼び出された瞬間からリクエストが終了するまで有効です。

■Parse.Cloud.beforeSaveやParse.Cloud.afterSaveはData Browserから直接Rowを追加した場合にも呼び出される

これは意外とハマりどころです。例えばData BrowserからUserを追加した時などにUserに対してつけておいたParse.Cloud.beforeSaveが発動するなどしてよく発生します。Data Browserから直接Rowを追加した場合、request.userはnullになりますので注意してください。また追加元がData Browserなのか普通のクライアントなのかを判定する手段が用意されていないため、処理を分岐させたくなるととたんに話が面倒なことになります。

Parse.com使ってみた

いまさらですがBaaS (Backend as a Service) が来てるらしいですので、とりあえずParse.comに手を出してみました。

■良かった所

  • クライアント側の実装が楽で安定しています。デバッグログも充実しており、Parseが原因でクラッシュするということもなく、特に悩まされるところはありませんでした。
  • 料金がとにかく安いです。個人で使うぶんには全く問題ないかなと思います。

■イマイチだった所

  • サーバーがUSなせいもあってそれほどレスポンスはよくありません。
  • セキュリティモデルをまじめに構築しようとするとかなり面倒くさいです。
  • Cloud Codeに山ほどハマりどころがあります。詳しくは別記事で。
  • バッチ(定期実行)に相当するものがありません。自宅のPCをから毎晩のタスクを定期実行するとかそういう悲しい方法で回避するしかありません。
  • Dev版と製品版で同じバックエンドを使うことになるので、公開したアプリの継続開発が面倒そうです。これは違う名前で開発版アプリを作ることで回避することができます。
  • 料金。エンタープライズで使うときの料金体系が不明瞭で、「連絡してね」の一言で済まされているため不安が残ります。
  • データの可搬性。一応Exportオプションは用意されていますが形式が独自形式のJSONなので自前で手元のDBなどへのImportツールを作る必要があり結構面倒だと思います。手軽にExcelやCSVでExportするオプションがほしいです。

■まとめ

プロトタイピングや小規模なアプリには良いと思います。ただしデータ可搬性をまじめに考えるのであればRESTful APIを使う必要があり、そうなってくるとせっかくよくできているクライアント側実装のほとんどが無駄になるため微妙に感じられます。Cloud Codeはハマリどころが多いのがまず問題ですが、わかってしまえば問題ないと思います。

2013年3月24日日曜日

Unity でソースコードに書いたリテラル文字列の文字コードを調べてみた

Unity3.5.6においてソースコード上にリテラル文字列として日本語を置いた時、時々ログ出力が上手くいかないことがあるということがわかり、ちょっと調べてみました。するとリテラル文字列を置いたソースコードの種類に応じて文字コードが違うということがわかりました。
  • C# (.cs) はUTF-16
  • JS (.js) はUTF-8
  • Boo (.boo) は不明
  • ネイティブのiOSはUTF-8
また出力する側、要するにDebug.Logメソッドは基本的にUTF-8のみを受け付けられるようになっているということがわかりました。まとめると以下の図のようになります。



最終的にJSファイルに全ての日本語リテラルをまとめて回避しましたが、そもそも日本語リテラルは使わず国際化文言ファイルみたいなものを別途用意しておいたほうが筋が良いと思います。iOSならLocalizable.stringsがありますしね。

2013年1月20日日曜日

SLComposeViewControllerでFacebook投稿する際に投稿が失敗してしまう問題

iOS 6.0より追加されたSocial.frameworkは大変お手軽に使用できて、ユーザーさんも毎回毎回素性の知れないアプリに対してTwitter/Facebookログインをし直すという手間と危険性から開放される便利な代物ですが、ちょっとした落とし穴を見つけたのでご紹介します。

SLComposeViewControllerを使っている時に、同じ文面でもTwitterには正常に投稿できるがFacebookには投稿に失敗してしまうというケースが発生することがあります。画面にはただ「Facebookに投稿できません」とアラートが表示されるだけですし、SLComposeViewControllerは投稿失敗時のerrorに対してコールバックblockもdelegateも存在しないので原因を調べることもできません。

実機のコンソールログを見てみると以下の様なエラーになっています。
Jan  8 11:01:25 akisute-no-iPhone sociald[6444] : 2013-01-08 11:01:25.665|sociald|0x1fd65e70: Request status was 400
Jan  8 11:01:25 akisute-no-iPhone sociald[6444] : 2013-01-08 11:01:25.668|sociald|0x1fd65e70: SLDFacebookPostUpload: The response indicates an error
 Parameters:{type = immutable dict, count = 1,
 entries =>
  2 : {contents = "error"} = {type = immutable dict, count = 3,
 entries =>
  0 : {contents = "message"} = {contents = "(#100) The parameter link is required"}
  1 : {contents = "type"} = {contents = "OAuthException"}
  2 : {contents = "code"} = {value = +100, type = kCFNumberSInt64Type}
 }
 
 }
 . 
 
 HTTP status 0
SLComposeViewControllerが裏で使用しているsocialdのSLDFacebookPostUploadクラスがエラーを吐いています。一見しただけだとOAuthExceptionとか書いてあって認証系のエラーかと勘違いしてしまいそうですが、実はこれSLComposeViewControllerのaddURL:メソッドに「空の」NSURLインスタンスを渡した時に発生するエラーです。以下のコードで簡単に実験することができます。

対策としてaddURL:しようとしているURLのschemeがnilまたは空文字列だったらaddURL:しないとすればOKです。しかしTwitterでは通るのにFacebookだけ通らないのはなんだか納得いかない・・・><

エンジニアサポートCROSS 2013で発表してきました

先日ニフティさんが主催されたエンジニアサポートCROSS 2013におじゃまさせていただきました。このエンジニアサポートCROSSは年に1回、去年から開催されているらしいのですが、なんといっても大手企業さんが主催ということで
  • 参加者がとにかく豪華
  • プレモル飲み放題ケンタッキー食べ放題という夢の様な環境
  • それでいてきちんとWeb系/Make系コミュニティのギークっぽい雰囲気のカンファレンスになっている、スーツではない
という独自の魅力があるカンファレンスになっていました。

で、このエンジニアサポートCROSSにはアンカンファレンス枠があって、参加者が自由気軽にその場でプレゼンを行う事ができる場がありましたので、せっかくだからということで私も発表させて頂きました。


内容については先日リリースしましたダンゴルのサーバサイド側の裏話です。といってもスライド見れば分かる程度のものです。

来年は正規のスピーカー枠で参加したいです><

2012年12月3日月曜日

Unity Asset Server でブランチ切ったりタグつけたりする方法

弊社のUnityプロジェクトではUnity Asset Serverを使ってソースコードやアセットの管理を行なっているのですが、以前ブログに書いた通りこのUnity Asset Serverさんは標準でブランチもなければタグもサポートしていないというCVS以下の素敵なシロモノです。しかしながらやはり開発のニーズ上、継続的に開発するためにはブランチやタグが必要になってきます。そこでUnity Asset Serverを使っていかにしてブランチやタグを運用するかという方法を考えてやってみましたので共有いたします。


■基本方針

基本方針は要するにSVNのやり方をパクります。すなわち、
  • タグやブランチはリポジトリのコピーとして表現する
  • リベースやマージは気合でなんとかする
以上二点です。

さてリポジトリのコピーですが、一応Unity Asset Serverではリポジトリのコピーの作成が可能になっています。



こちらをクリックしてリポジトリをコピーしてください。注意点としてはこのリポジトリコピーは他のユーザーが一人でもAsset Serverに接続しているとコピーが出来ないので、社内に呼びかけて全員のUnityをシャットダウンするなり何なりしてください。誰が接続しているか特定したい場合はUnity Asset Serverが動いているサーバで
ps aux | grep unity
とか叩けばなんとなくわかります。


■タグを付けたい

これは簡単です。Asset Serverに接続して、タグが付けたいバージョンがヒストリの先頭にある状態で、先述したリポジトリのコピーを行います。あとはコピーしたリポジトリに触らないようにすればタグの完成です。

注意点として、タグが付けたいバージョンがヒストリの奥のほうにあると基本的には綺麗にタグが切れません。そのようなコミットをする前にタグを切ってください。


■ブランチを切りたい

これもまだ簡単です。Asset Serverに接続して、ブランチの根っこにしたいバージョンがヒストリの先頭にある状態で、先述したリポジトリのコピーを行います。あとはこちらのリポジトリに作業者全員が接続先を切り替えて、新しいコミットを重ねていけば良いです。

注意点として、タグと同様に例によってバージョンがヒストリの奥のほうにあると綺麗にブランチが切れず苦労することになりますので、コミットの重ね方には最新の注意を払う必要があります。

それから各作業者がブランチを切り替える際の手順にも注意する必要があります。
  1. Asset Serverに接続してdisplayを選択。
  2. 新しいブランチとなるリポジトリを選択してconnect。
  3. リポジトリの切り替えが終わったらupdateを行う。
  4. マージするかどうか聞かれたら、ブランチの切り替えなので、すべてDiscard my changesを選択すること。

■ブランチをリベースしたい

ここからがちょっとした地獄の始まりです。まずはリベースから。例として1.0.1ブランチのブランチ元である1.0.0をリベースする手順を示します。
  1. Asset Serverに接続して、リベース元となるブランチ (1.0.0) にconnect。
  2. リポジトリの切り替えが終わったらupdateを行う。
  3. マージするかどうか聞かれたら、ブランチの切り替えなので、すべてDiscard my changesを選択すること。
  4. Asset Serverに接続して、リベース先となるブランチ (1.0.1) にconnect。
  5. リポジトリの切り替えが終わったらupdateを行う。
  6. マージするかどうか聞かれたら、リベース元のコードをすべて新しい接続先のブランチに上書きしたいという処理になるので、ソースコードとシェーダーコードについてはMergeを、その他のシーン、プレファブ、テクスチャ、モデル、音などはすべてIgnore server changesを選択する。
  7. このままだとなぜかコードは変更されているのに変更差分をUnityが認識しない悲しい状態になるので、メニューからAssets > Reimport allを選択して変更差分をUnityに認識させる。
  8. マージに失敗したコードおよびシーン、プレファブ、テクスチャ、モデル、音などを手でマージする。
  9. コミットして完了。
これで何とかリベースっぽいことができるようになります。


■ブランチをマージしたい

ブランチのマージは単にリベースの逆をやるだけです。例として1.0.1ブランチをmasterにマージする手順を示します。
  1. Asset Serverに接続して、マージ元となるブランチ (1.0.1) にconnect。
  2. リポジトリの切り替えが終わったらupdateを行う。
  3. マージするかどうか聞かれたら、ブランチの切り替えなので、すべてDiscard my changesを選択すること。
  4. Asset Serverに接続して、マージ先となるブランチ (master) にconnect。
  5. リポジトリの切り替えが終わったらupdateを行う。
  6. マージするかどうか聞かれたら、マージ元のコードをすべて新しい接続先のブランチに上書きしたいという処理になるので、ソースコードとシェーダーコードについてはMergeを、その他のシーン、プレファブ、テクスチャやモデルや音などはすべてIgnore server changesを選択する。
  7. このままだとなぜかコードは変更されているのに変更差分をUnityが認識しない悲しい状態になるので、メニューからAssets > Reimport allを選択して変更差分をUnityに認識させる。
  8. マージに失敗したコードおよびシーン、プレファブ、テクスチャ、モデル、音などを手でマージする。
  9. コミットして完了。
見ての通り、リベースとほとんど同じですね。

2012年12月1日土曜日

PySpa アドベントカレンダー 1日目 〜バカとPythonと芳泉閣〜

PySpaアドベントカレンダーというイベントに参加してみたところ、僭越ながら初日を努めさせていただくことになりました>< ということで本日は技術ネタではなくてPySpaというイベントとともに自分の職歴でも振り返ってみようと思います。


■そもそもPySpaってなんぞや

vの人という主犯格が定期開催している温泉旅館に泊まるイベントです。名前に反して実はPythonは全然関係ないです。詳細は以下のページとか見てみてください。
https://github.com/pyspa/pyspa
http://voluntas.hatenablog.com/entry/20081024/1218125470

基本的にvの人の知り合いばかりで固定PySpaメンバーと言えるメンバーがいるのですが、昔からいた人が仕事の都合とかで疎遠になると新しい人が定期的にやってきて全体が保たれているという感じの不思議な輪が形成されているのが特徴ではないかと思っています。後、全員やたら技術力があります。


■SIer時代(2008~2009年)

最初に参加したのが2008年に開催された第4回です。記憶が曖昧なのですが、確かTwitterだか何だかで参加者を探していたところに無理やり飛び込んだのがきっかけです。よくやった当時の自分。当時は新卒入社したSIerの会社でJavaを書いていて、Pythonって面白そうだなーとか考えて手を出していたころだったのでPythonの勉強会のノリで参加してました。あとそういえばiPhone 3Gを発売日当日に買い、Apple信者生活を開始しました。

第4回の記録
http://akisute.com/2008/10/4python-1.html

うん、今見たら恥ずかしくて死にたい。といっても年中後から振り返ったら恥ずかしくて死にたいようなことしかしてない気がするので今更気にしたら負けです。次行きます。次。
第5回からは完全にiPhone開発ばっかです。あとこの一年で随分PySpaのノリを理解した感じを文体から感じ取れます。

第5回の記録
http://akisute.com/2009/06/5-python.html

この期間は自分の基礎となる技術や興味を見つけることができた貴重な時期でした。最も向上心がありバックグラウンドもない新人時代を非常に有意義に過ごすことができたのではないかとおもいます。あと、今現在わずかに残っているのみとなった社会人として必要な常識などは全てこの時期に身につけさせていただきました>< 本当にありがとうございました><


■Web屋時代(2010年~2011年)

2009年末に新卒入社したSIerの会社を退職してビープラウドに転職しました。転職理由はもはや覚えていないのですが、確かこのままこの会社にいてはスキルアップにならない!よりよい環境へ移るべきだ!などという意識の高い社二病精神か何かが原因だった気がします。

このへんから面倒になったせいかPySpaメンバーの内輪みたいな感じになったせいもあるのかブログへの参加記録が途絶えてしまっていますが、PySpa自体には二年間毎回かかすことなく参加しておりました。というのもPySpa自体がビープラウドの非公式社外リクルートイベントみたいな感じになっていた関係上、半数近くの社員がPySpaに参加する時があったりしたからです。

例えば今回のアドベントカレンダー参加メンバーだと

12/1 akisutesama
12/3 tokibito
12/4 torufurukawa
12/8 shimizukawa

あたりがPySpa経由で雇用されたビープラウド社員だったりします。

第6, 7, 8, 9, 10と参加してきたPySpaですが、10回でいったん定期開催を締めようというvの人の考えで第10回を最後にしばらく開催が途絶えてしまいました。そのかわり定期開催する文化はPyFesへと引き継がれていきました。

この期間は良い意味でも悪い意味でも自分のアイデンティティが確立された期間でした。何か捨ててはいけないたぐいの常識を投げ捨ててしまった変わりに職業iOSプログラマとしてのキャリアが確立された感じでしょうか。あとは仕事でひどく失敗した時期でもありました。前職SIer時代では失敗ができるような機会はなかったのですが、ビープラウドでは数回ひどく失敗してご迷惑をお掛けしたことがありました。ほんとスミマセン>< お陰様で人類としての社会常識はなくなりましたがプロとして仕事を進める常識は多少身につきました><


■ゲーム屋時代(2012年~)

2012年の2月にビープラウドを退職して変なゲーム会社に転職して以来、しばらくご無沙汰していたPySpaですが、今年の10/26に開催されたのでふらっと参加してきました。

感想、みんな年食い過ぎ。

高齢化の並はPySpaにも押し寄せているのかいないのかわからんのですが、第4回第5回の頃の大学生のきゃっきゃうふふ的ノリはかなり鳴りを潜め、仕事の話をしたりだとかが増えたり徹夜組が全滅して朝早起きになってたりお菓子の減りが悪くなってたりと随所におっさん臭がしてきております。ピンチです>< まぁ時間の流れというのはそういうものなのかなぁと私自身おっさん的に思っております。

この期間は自分のこれまでの集大成であるような気がしています。子供の頃にハマりまくっていたゲームへの愛情と、SIer/Web屋時代に培ったサーバ側技術と、iPhoneリリースからやってきたiOS開発の集大成という感じです。そして随分と責任ある立場をまかされるようになってしまった気がします。うーん年だ。このあとどうしよう。とりあえず今しばらくはゲームが最高に面白いのでゲームをやろうと思ってます。

余談ですがうちらのゲームもうすぐリリースらしいです。一応宣伝。
http://www.donpy.net/appinfo/18791.html




■まとめ

こうして振り返ると私の仕事人生はiPhoneとPySpaとともに歩んできたんだなぁと思います。iPhoneは私に夢中になって開発できる何かをくれましたし、PySpaは私にスキルと人脈と情熱をくれました。この2つがあったからこそここまでやってこれたんだなぁと思っています。これからもまぁそんな感じで適当にやっていきます。

最後になりましたけれども、PySpaを毎年開催してくださっているvの人と、今回のアドベントカレンダーを企画していただいたとんぷーさん、どうもありがとうございます!

それでは明日はshkumagaiさんよろしくおねがいしまーす!

2012年11月12日月曜日

Unity 3.5 以下でプリプロセッサ定義を上手く使う方法

C/C++/Objective-Cベースのプロダクトのビルドシステムを構築するときに大変便利なのがプリプロセッサのdefineマクロです。defineマクロを使って環境を切り替えたり不要なログコードを削除したりなどは皆さんよくやってるかと思います。C#にも同様のプリプロセッサ定義が用意されているみたいですので、こちらを使ってUnityプロジェクトのビルドシステムを構築できないかと思ってやってみました。


■プリプロセッサ定義の使い方 (Unity 4以降)

Unity 4.0よりプリプロセッサ定義がUnity本体によってサポートされるようになりました!ビルドスクリプトからも自由にアクセスが可能になっており、非常に簡単に扱うことが可能です。
詳しくはけいごさんのブログに完璧にまとめられていますのでそちらをご覧ください。
http://anchan828.tumblr.com/post/32669868103/define


■プリプロセッサ定義の使い方 (Unity 3.5以降)

ここからが本題になります。Unity 3.5以前はプリプロセッサ定義を公式にサポートしていません。そこで以下の4種類のファイルをAssetsフォルダ直下に置くことでプリプロセッサ定義を読み込ませます。
/Assets/smcs.rsp (C#用)
/Assets/gmcs.rsp (C#エディタスクリプト用)
/Assets/us.rsp   (UnityScript、俗にJSと呼ばれている物用)
/Assets/boo.rsp  (Boo用)
このrspファイルにはC#コンパイラのコンパイラオプションとして渡すオプションが記述できます。ですので http://linux.die.net/man/1/mcs などに列挙されているコンパイラオプションであればひと通りなんでも使用可能です。今回はプリプロセッサ定義をやりたいので、以下のように書けばOKです。
-define:DEBUG
複数の定義が書きたい場合は、
-define:DEBUG -define:USE_DEV_SERVER
のようにスペースで空けて複数記載するか、
-define:DEBUG
-define:USE_DEV_SERVER
のように改行して複数記載するか、
-define:DEBUG;USE_DEV_SERVER
のようにセミコロンで列挙して書くことができます。注意点として、C/C++/Objective-Cのdefineマクロと違って
-define:DEBUG=1
のように値を定義することはできないみたいです。あくまでシンボルを作るだけみたいですね。

以下Twitterでのやりとりです。

さて、これでプリプロセッサ定義はバッチリできるようになったのですが、問題はこれをビルドごとに書き換える方法です。最初はビルドスクリプトでこのrspファイルを書き換えていたのですが、どうもこれをUnityが全く認識しないのです。普通にファイルをただ書き換えてもダメなようです。

そこで黒魔術を導入します。以下のスクリプトで使われているコードを利用して、無理やり書き換えた後のrspファイルをUnityに認識させます。
https://github.com/prime31/P31UnityAddOns/blob/master/Editor/GlobalDefinesWizard.cs#L131
AssetDatabase.Refresh();
reimportSomethingToForceRecompile();

private void reimportSomethingToForceRecompile()
{
 var dataPathDir = new DirectoryInfo( Application.dataPath );
 var dataPathUri = new System.Uri( Application.dataPath );
 foreach( var file in dataPathDir.GetFiles( "GlobalDefinesWizard.cs", SearchOption.AllDirectories ) )
 {
  var relativeUri = dataPathUri.MakeRelativeUri( new System.Uri( file.FullName ) );
  var relativePath = System.Uri.UnescapeDataString( relativeUri.ToString() );
  AssetDatabase.ImportAsset( relativePath, ImportAssetOptions.ForceUpdate );
 }
}
これでC#で書かれたコードに対しては無事にrspファイルへの変更が反映されるようになります。

しかしながら更に落とし穴があります。UnityScript(JavaScript)で書かれたファイルに対してはこの黒魔術が効きません。したがってUnityScriptで書かれたファイルに対して動的にus.rspファイルの定義を適用することができないようです。すべてのJSファイルに対して上記の黒魔術を適用しても効果がなかったため、おそらくダメだと思われます。


■結論

UnityScriptは使わないようにしましょう。

2012年11月11日日曜日

iOS 6.0の advertisingIdentifier と identifierForVendor にはバグがあるので注意

いささかタイミングを逃した感が強いのですが、厄介なバグにぶち当たってしまったので共有いたします。

iOS 6からUDIDに変わる識別子としてUIDeviceのidentifierForVendorとASIdentifierManagerのadvertisingIdentifierが使えるようになったのはすでにみなさんご存知かと思います。ですがどうもこやつらiOS 6.0だと正しく機能しない場合があるようなのです。

詳細は以下のとおり。
http://stackoverflow.com/questions/12605257/the-advertisingidentifier-and-identifierforvendor-return-00000000-0000-0000-000

こちらの情報元によると、iOS 6.0に Over-The-Air アップデート (iTunesを使わないで端末からアップデートする方法) するとこれらの識別子が常に00000000-0000-0000-0000-000000000000を返してしまうらしいのです!iOS 6.0.1では修正されているらしいです。

見事に私の UIApplication-UIID ライブラリもこのバグを踏んづけて大爆発してしまいました。

対処法としては生成されたIDが00000000-0000-0000-0000-000000000000でないか文字列比較する方法がよさそうです。

2012年9月26日水曜日

Unity の PostprocessBuildPlayer を使って Weak Framework を追加する方法

※2013/11/27追記: 第二版を公開しました。

UnityでiOSのアプリを作っていて困ることの一つに、iOSが提供するシステムフレームワークへのリンクをプロジェクトに追加するのが超面倒くさいという問題が挙げられます。UnityがiOSアプリを書きだした後、手動でXcode上からシステムフレームワークを追加してもいいのですが、これはとんでもなく面倒です。

そこでUnityジャパンの伊藤さんという方が PostprocessBuildPlayer という仕組みと Ruby の xcodeproj ライブラリを使ってビルド時に自動的にシステムフレームワークを追加する仕組みを公表してくださいました。お陰様で随分とはかどっていたのですが、その方法では実はシステムフレームワークをWeakリンク(Optionalリンク)することができなかったのです。これでは例えばSocial.frameworkを使うアプリをビルドしてiOS5で動かすと起動時に問答無用でクラッシュしてしまいます。困りました。iOS6/5両対応ができないと話になりません。

というわけで作りました。システムフレームワークをWeakリンクできるPostprocessBuildPlayerを。こちらです。


ライセンスはMITライセンスにしておきました。
使い方は大体見ればわかるかと思いますが、まず最初にgem経由でxcodeprojをインストールしておくこと。
sudo gem install xcodeproj
あとは上記のPostprocessBuildPlayerをUnityプロジェクトの /Assets/Editor 以下に配置して、コード中のフレームワーク名を指定している箇所をご自身のお好きなように変更してやればオッケーです。

Unity 3.5.5 以下で Game Center / iAd / UIImagePicker などを使用したアプリが iOS 6 でクラッシュする問題

現在 Unity 3.5.5 以下でビルドしたiOSアプリが、以下の条件をすべて満たしているとクラッシュしてしまう問題が発生しているようです。
  • UnityのiOSアプリビルド設定で、画面方向を横向き(Landscape Left/Landscape Right)のいずれかのみに設定している。
  • Pluginなどを経由してGame Centerを使用している。またはiAdやUIImagePickerなどのiOSが提供する特定のView Controllerを使用している。
  • iOS 6を搭載したiPhone/iPod Touch上で動作させる(iPadは大丈夫)。
詳細はこちら。
http://developer.coronalabs.com/forum/2012/09/17/ios-6-orientation-crash





すでにUnity側で問題は把握しているようで、現在修正版の3.5.6を用意してくださっているようなので、続報を待ちましょう。・・・といっても、すでにUnity 3.5.5以下でビルドされたiOSアプリをリリースしていて、しかもAsset Bundleを使用していたりすると、Asset Bundle間の後方互換性問題のためかなり厄介なことになると思われます。最悪過去のバージョンのサポートをすべて切る必要が出てくるかもしれません。


さて、ここからは技術話の余談です。

このクラッシュ問題なのですが、原因はiOS 6で変更になった画面回転(Auto Rotation)APIにあると思われます。iOS 6からはなんとこれまで画面回転に使用されていた
UIViewController shouldAutorotateToInterfaceOrientation:
が完全に廃止になっており、基本的には全く呼び出されないようになってしまっています。その代わりにより体型だった画面回転の仕組みが導入されています。iOS 6からの画面回転は、「アプリが対応する画面方向」と「各View Controllerが対応する画面方向」の2つによって画面の回転する方向が決定されるという仕組みになっています。

ここで、アプリが対応する画面方向は以下のように決定されます。
以下優先順位順に、
1. UIApplicationDelegate application:supportedInterfaceOrientationsForWindow: が返す向き。iOS 6以降のみ。
2. UIApplication supportedInterfaceOrientationsForWindow: が返す向き。iOS 6以降のみ。
3. Info.plist で指定されている UIInterfaceOrientation の向き。
各View Controllerが対応する画面方向は以下のように決定されます。
各ViewControllerが supportedInterfaceOrientations を実装しているなら、それが返す向き。
していないならば、
iPhoneだと UIInterfaceOrientationMaskAllButUpsideDown
iPadだと   UIInterfaceOrientationMaskAll
この2つの積集合をとって、両方が一致した向きに画面回転が行われる仕組みになっています。

では、ここで両者が全く一致しない場合はどうなるでしょう?答えは簡単でクラッシュします。ワオ。素敵。ふざけんなバカApple爆発しろ。

それを踏まえると、今回の問題でクラッシュしてしまう仕組みはこう考えられます。
  1. Unity 3.5.5以下が書き出すiOSアプリは当然ながらiOS 6に完全対応していない。
  2. Game Centerなど、Appleが提供しているUIコンポーネントは全てiOS 6の画面回転に対応しているが、それらのうち幾つかのものはiPhoneだと縦向き画面にしか対応していないものがある(iPadは基本縦横どちらでも表示できるように対応する必要があるとされているため、無事のようです)。
  3. Unityが書きだしたアプリは横向き画面にしか対応していないのに、上記のView Controllerは縦向きにしか対応していないと言い出すので、クラッシュする。
やれやれですね><
ちなみに対応策としては、アプリ自体は縦方向にも横方向にも対応しているというふうにapplication:supportedInterfaceOrientationsForWindow:メソッドを使って値を返すようにした上で、コンテンツを表示するUIViewをUIViewControllerに管理させるようにして、UIViewControllerのsupportedInterfaceOrientationsで横向き画面の値だけを返すようにするといいかんじになると思います。しかしながらiOS 5/6両方で上手く回る画面は結構大変そうです。

2012年8月19日日曜日

Unity のプラグインで iOS の bundle を使えるようにする方法

OS XやiOSには Bundle という仕組みがありまして、 NSBundle というBundleを扱うためのクラスが用意されています。皆様も一度は
[[NSBundle mainBundle] pathForResource:@"MyMusic" forType:@"mp3"];
みたいなコードを書いたことがあると思います。このBundleの仕組みを使うと、
  • 複数の画像や文言、JSONなどのデータファイル、音楽などを一つにまとめて扱うことができる。個別のファイルとしてプロジェクトに加えなくてよいので利便性が良い。
  • Bundleには最初から多言語化リソースを扱うための仕組みが用意されているため、多言語化が非常に簡単にできる。
  • OS Xだけになりますが、Bundleにはコンパイル済みのコードを含められるので、プラグインの仕組みが簡単にできる。
以上のようなメリットがあります。例えば実例を上げると、Facebook SDKなどがBundleの中に画像や文言などのリソースを格納して配布するようになっています。実際には確認できていないのですが、おそらくmobage, GREEのSDKもそのようになっているのではないでしょうか?ということでSDKなどを配布するときには非常に便利です。

で。このBundleによる配布はなかなか便利なので、UnityのiOSプラグインとして配布するときにも是非使いたいのですが、そのまま/Assets/Plugins/iOS以下にBundleを配置しても正しくBundleが認識されませんし、iOSのアプリにインストールされません。

そこでBundleを配布するときは、/Assets/Plugins/iOS/以下ではなくて、/Assets/StreamingAssets/以下にBundleを配置するようにしましょう。実は/Assets/StreamingAssets/以下のパスには隠し要素があって、このパス以下のファイル・ディレクトリは全てアプリケーション自身の/Data/Raw/ディレクトリに配置されるようになっています。
参考: http://sehm.blog48.fc2.com/blog-entry-159.html

あとはプラグインとして用意したiOSコードの中で以下のようにしてBundleを取得すればOKです。
NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"MyBundle" ofType:@"bundle" inDirectory:@"Data/Raw"]];
これでUnityプラグインを多言語化したり画像リソースを使ったりするのが楽になると思います。

将来的にUnityのバージョンが上がって、/Assets/Plugins/iOS/以下においたBundleも扱えるようにしてくれると楽なんですが・・・Unity 3.5の地点ではどうもダメっぽいです。

2012年7月25日水曜日

LLDB を使って CUI で動作させているテストケースをデバッグする

GHUnit のテストケースを Jenkins で自動的に走らせるために CUI のテストを作っているのですが、 GUI を使ったテストでは問題なく通るのに CUI を使ったテストのときだけテストが落ちるという問題が発生してしまいました。 Xcode 経由の実行であれば Instruments だろうが内臓のデバッガだろうが使い放題なのですが、 CUI となるとそうもいきません。そこで LLDB を直接使って CUI で動作させているテストケースを直接テストしてみることにしました。

参考にしたのはこちら。
http://lldb.llvm.org/tutorial.html

さっそくやってみましょう。lldbコマンドで LLDB の対話環境を起動した後、
process attach --name MyApp --waitfor
でMyApp.appという名前のプロセスが立ち上がるのを監視します。



この状態でMyApp.appというアプリを起動すると、上の画像のようにばっちり LLDB がプロセスを検知して捕まえてくれます。今、MyApp.appはポーズ中になっているので、適当な箇所に
breakpoint -f MyTestModel.m -l 123
とかやって適当にブレークポイントを設置した後、
thread continue
で続きを実行開始します。



ご覧のとおりバッチリブレークポイントで捕まえることに成功です。こちらの図はEXC_BAD_ACCESSが発生した時になんか自動的に止めてくれたときのものです。Xcode経由で起動するときに比べれば不便ですが、何もないよりはだいぶはかどりますよ。

2012年6月24日日曜日

__has_feature(objc_arc_weak) を使って賢く安全に ARC/Blocks を使う

iOS 6も発表されて、皆さんARCやBlocksをガンガン使用する感じのプログラミングスタイルに変化してきていると思うのですが、そこで問題になってくるのが後方互換性の話です。特にiOS 4。Blocksを使うとなるとどうしても以下の様に非同期で実行されたBlocksの中からViewを書き換えるようなコードを書きたくなるのですが、
__weak MyViewController *__weakSelf = self;
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse* response, NSData* data, NSError* error){
    __weakSelf.label.text = [[NSString alloc] initWithData:data encoding:NSUTF8Encoding];
}];
このようなコードを安全に実行するためにはselfを一度__weakな変数に代入して、それをBlocksにキャプチャさせるようにしないと、以下のような理由で安全ではなくなってしまいます。
  • __strongを使うと、対象の変数をキャプチャしているBlocksの実行が終わるまで対象の変数がreleaseされなくなるばかりか、最悪の場合は循環参照が発生してメモリが絶対に開放されなくなってしまいます。
  • __unsafe_unretainedを使うと、Blocksの実行が終わるまでの間に対象の変数がreleaseされてしまうとEXC_BAD_ACCESSでクラッシュします。
しかしながらiOS 4では__weakが使えず、状況に応じて__strongや__unsafe_unretainedでごまかす必要があります。このようなときにiOS 5では__weakを使い、iOS 4やno-ARCなプロジェクトではそれなりに適切な何かを使って実装するような仕組みが欲しくなります。

そこで便利に使えるのが__has_feature(objc_arc_weak)__has_feature(objc_arc)マクロです。こいつらを使うと簡単に現在のビルド環境・ターゲット環境がARCを導入しているか、weakは使用可能か、を判断できます。たとえば私は以下の様なマクロを組んで、
// ARC & memory management
// Use these prefixes to be compatible with ARC on iOS 5/ ARC on iOS 4.X / non-ARC
// 
#if __has_feature(objc_arc_weak) // iOS 5 or above
#define __my_block_weak        __weak
#define __my_block_weak_unsafe __weak
#elif __has_feature(objc_arc)    // iOS 4.X
#define __my_block_weak        __strong
#define __my_block_weak_unsafe __unsafe_unretained
#else                            // iOS 3.X or non-ARC projects
#define __my_block_weak        __strong
#define __my_block_weak_unsafe __block
#endif
こんな感じのコードにしてます。
__my_block_weak MyViewController *__weakSelf = self;
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse* response, NSData* data, NSError* error){
    __weakSelf.label.text = [[NSString alloc] initWithData:data encoding:NSUTF8Encoding];
}];
こうするとどの環境でも(比較的)安全にblocks内部でselfを触ることができるという寸法です。

ここで気になるのが__has_feature(objc_arc_weak)の判定条件です。個人的にこいつはiOS SDK 5.0以上を使っていたらターゲット環境がiOS 4とかiOS 3とかでも無条件で1を返してしまって使えないんじゃないのかと危惧していたのですが、なんとIPHONEOS_DEPLOYMENT_TARGETの値を見てきちんと値が変化する仕組みになっています!なので例えばSDKは最新だけれどiOS 3もサポートしたいみたいなプロジェクトでは__has_feature(objc_arc)の値が自動的に0になって良い感じに分岐してくれるというわけです。安心して使いまくりましょう!

2012年5月5日土曜日

C# で map とか reduce みたいな楽しいリスト操作をしたい

プログラミング言語がロジックを組むのに向いているかいないかを判断するときの基準に、私はよく「文字列の操作が優れているか否か」「配列・辞書・集合の操作が優れているか否か」を評価点に挙げます。文字列や配列、辞書、集合の操作はほとんどすべてのアプリケーションで必要になり、それらの生産性が高く高速に処理してくれる言語ほど簡単で高速なロジックが組めると思うからです。

そういう意味でObjective-Cを考えると、文字列の操作はまぁまぁ良い(特にUnicode周りがなかなか優れている、正規化もできるし)のですが、配列・辞書・集合の操作がイマイチで、作るの面倒なら操作するのも面倒。さらには良く欲しくなる以下の操作が欠けています。
  • map - 条件式を渡して、もとの集合の各要素に条件式を通した結果を新たな集合として返す。
  • reduce - 条件式を渡して、要素を前から順番に計算して畳み込み、集合から一つの要素にする。
  • any - 一つでも要素が条件式を満たすならtrue, すべての要素が満たさないならfalse
  • all - すべての要素が条件式を満たすならtrue, 一つでも満たさないならfalse
ではMono上のC#ではどうなんだろうということで調べてみたところ、LINQを提供するSystem.Linq名前空間に高度な配列・辞書・集合操作を行うための拡張メソッドが用意されているということがわかりました。

http://docs.go-mono.com/?link=T%3aSystem.Linq.Queryable
http://msdn.microsoft.com/ja-jp/library/system.linq.queryable(v=vs.90).aspx

ということで早速使ってみます。



実行速度が高速なのかどうかはわからないのですが、なかなか面白いです。ラムダ式が使えるのもスマートで素敵ですね。うーん、C#好きになってきたかも。

Mono の System.String と string の違いについて調べてみた

MonoとかC#とか初心者なのでSystem.Stringとstringの違いがよくわからず、気になったので調べてみました。

以下のページのベストアンサーが一番わかり易かったです。
http://okwave.jp/qa/q7225655.html

ちょっと転載します。
string と System.String は型として使われる限り単なる別名なので同じものです。
foo.System.String みたいなものが用意されて foo 名前空間内から使うような場合は異なりますが,特殊例過ぎるのでこれは考えないものとします。
コンパイラは,ソース上の型として string と書かれているものは,System.String とかかれているものとして処理します。
# 正確には "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" という型 (.NET 4 の場合)

これは,SDK 付属の逆アセンブラでコードを見ると,string を使っても System.String を使っても同じコードになることから確認できます。

同じように,int は System.Int32 の別名ですし,bool は System.Boolean の別名です。


使い分けは,特別決まりはありません。
唯一,メソッド名等に使う場合には言語固有の名称を避ける (CLR の名前を使う),というのはあります。
MSDN: 一般的な名前付け規則
http://msdn.microsoft.com/ja-jp/library/ms229045.aspx
具体的には,
・ToInt
よりも,
・ToInt32
の方が好ましい,ということです。
# 上側の名前付け規則だと,Visual Basic においては ToInteger であるべき,となる。


私は,static メソッドの呼び出しに使う場合は CLR の名前を使い,それ以外では言語固有の名称を使っています。
書籍によっては,常に CLR の名前を使うべき,という物もあったりします。
# が, for (Int32 i = 0; ……みたいなコードはほとんど見ません。

自分なりの物でいいので,統一したルールを用意しておくのがよいでしょう。
# 常に言語固有の名称でもよいと思います。

そもそも.NET Framework (とMono) は実装言語に依存しないような作りになっている (CLRというやつ?) のでこのような仕組みになっているようです。なるほど。 int, bool, string はC#の型で、 System.Int32, System.Boolean, System.String はCLRの型なわけですな。勉強になりました。

Unity でシステムが使用しているリソースを一覧表示したい

簡単なEditor拡張機能を書くときとか、デフォルトでUnityのエディタが使っている画像とか借りて表示したいときが多々あるんですが、これが実は公開されていなくてそのままでは使えないのです。ということでデフォルトでUnityのエディタが使っているリソース一覧を暴くスクリプトを用意してみました。



実行するとログに全てのリソースの一覧が表示されますので、あとはそれっぽい名前のやつを適当に拝借すればOKです。

自作の Unity Editor Script を github に公開してみた



最近は仕事の関係でUnityばっかり触っているのですが、中でも今お気に入りなのがEditor拡張機能です。これは自分で簡単なスクリプトを書くだけでUnityのエディタ上の表示を自由にカスタマイズできる機能なのですが、コイツの出来がなかなか素晴らしいのです。これまでいろんな開発環境を触ってきたのですが、ここまで簡単にエディタ上の表示を自在にカスタマイズできる環境は他に類がありません。

ということで調子に乗って自作のEditor拡張機能を書いて公開してみることにしました。まずは簡単なものからということで、シーン上に配置できる定規を作りました。


■機能
  • 原点からの距離(u)、高低差(u)、対象位置地面の水平方向傾き(度)を測定可能 ※1u=Unity上での長さの単位1とします
  • イメージを見ての通り全数値がエディタ上に表示されるので一目でわかる
  • Raycast飛ばしてるので確実に地面位置を基準にして判定してくれる、Raycastが外れても空中の座標がきちんと出る隙を生じぬ二段構え
  • 画面上の色/フォントを自由にインスペクタから変更可能
  • すべてEditorScript/Gizmoなので万が一何かの間違いでリリース版のシーンに残っていてもMesh Rendererが走って画面に表示されるという悲しい思いをしない
  • 操作は原点を選択してAdd Pointボタンを押して出てきた点を任意の位置に移動して配置するだけ
  • Clear Pointボタン付き
ひと通り基本的なのは揃えてみました。


次は高低差メッシュをTerrainの上に表示する機能とか作ってみたいっすね。

2012年5月4日金曜日

Unity の GUIStyle でデフォルトで指定できるスタイル一覧

今回は完全に自分用メモになってしまいますがご了承ください><

UnityのGUIStyleはname文字列を指定して生成する事が可能ですが、Unityがデフォルトで持っているGUIStyleの一覧を見つけたので列挙しておきます。
  • box
  • button
  • toggle
  • label
  • textField
  • textArea
  • window
  • horizontalSlider
  • horizontalSliderThumb
  • verticalSlider
  • verticalSliderThumb
  • horizontalScrollbar
  • horizontalScrollbarThumb
  • horizontalScrollbarLeftButton
  • horizontalScrollbarRightButton
  • verticalScrollbar
  • verticalScrollbarThumb
  • verticalScrollbarUpButton
  • verticalScrollbarDownButton
  • scrollView
大文字小文字は関係ないみたいです。たとえばboxのところをBoxと指定しても問題なくそのまま通ります。

参考URL: http://answers.unity3d.com/questions/9844/copypaste-guistyle-in-the-inspector.html
参考URL: http://unity3d.com/support/documentation/Components/gui-Customization

2012年4月22日日曜日

Unity Asset Serverを導入してみた

先日のiphone_dev_jp東京の勉強会での発表資料に書いた内容と同じなのですが、結局あの場では発表できませんでしたので、改めてUnity Asset Serverを触ってみた感想などを書いてみようかと思います。


■Unity Asset Serverって何?

Unity社が提供している、Unityのエディタと完全に統合されたバージョン管理システムです。
http://unity3d.com/unity/team/assetserver/
ソースコードだけではなく、プレファブやシーンを含めたUnityのプロジェクト全体のリソースを管理してくれます。Unityのエディタと統合されているため、Unityのエディタから一切外に出ることなくバージョン管理ができるというのが売りです。実はUnity Asset Serverは完全に普通のPostgresSQLのサーバーをそのまま利用しているだけになっていますので、SQLを経由してバージョン管理の履歴を操作したりも出来ます。


■Unity Asset Serverを使う理由は?

なんといっても以下の3つがUnity Asset Serverの魅力でしょう。
  • 導入するのが非常に簡単。サーバー側はインストーラーをぽちぽちするだけでWindows, Mac, Linuxどの環境でも一発です。クライアント側はUnityにそのまま付属されてくるためインストールなんぞ一切不要です。Team Licenseをアクティベーションしたらすぐに使えます。
  • 運用するのが非常に簡単。管理者側もユーザー側も、バージョン管理未経験の人でもUnityエディタのGUIを経由して誰でも簡単に使用することができます。
  • 動作がそこそこ高速。バックエンドがPostgresSQLなおかげだと思うのですが、LAN環境で最大10MB/s程度の速度でコミットしたりアップデートしたりできています。これはテクスチャや音楽、3Dモデルなどの巨大なバイナリファイルを大量に扱うゲーム開発においてはかなり重要です。

■でもお高いんでしょう?

はい。お一人様5万円となっております。

お一人様、5万円です。

マジです。

なかなかボッタクリ挑戦的な価格設定だと思います。


■よかったところ

実際に2ヶ月間ほど運用してみてよかったところはこんな感じです。
  • だれでも超簡単に使えます。とにかく超簡単。これはプログラムなんて全くわからないデザイナーさんや、バージョン管理未経験の人、はたまた入社2日目の人でもなんの問題もなく使えている事実から裏付けされています。Asset Server導入前はgitを使っていたのですが、GUIクライアント付きでもトラブルだらけの毎日でした。これがAsset Serverになるやいなや全く教育もトラブルシュートもしないまま一日80コミット以上をコンスタントに記録するような素晴らしいバージョン管理体制が構築できたのです。
  • Unityのプロジェクトをバージョン管理するとき固有で発生するトラブルが一切ありません。まぁ具体的には先日書いた記事の通り、metaファイルなんですけど。前にも書きましたが、とにかくトラブルが発生しづらいです。簡単で単純なので。

■いけてないところ

さてもちろん良いところがあれば悪いところもあるわけで。以下のような点が問題点としてあげられます。
  • 高い
  • 高い
  • 高い
  • 高い
  • バージョン管理に必須とも言える機能が大幅に欠落しています。Subversion以下程度の機能しかありません。
  • 具体的にはブランチがない、タグがない、外部ツールがないのでJenkinsみたいないUnity以外から触ろうとすると超面倒くさいかPostgreSQLに直接SQL発行するしかない、基本コミットとアップデートとlog見てrevertするぐらいしかできることがないです。
  • みんなが一番期待するであろう、シーンやプレファブのマージですが、出来ません。一切できません。したがって作業範囲が衝突した時のトラブルはSubversionやgitと何ら変わりません。むしろスクリプトのマージを自動解決してくれるぶん、gitやhgのほうが優れています。
  • Unityのプロジェクト固有の問題は一切ないのですが、一般的なバージョン管理システム的にありえないバグが時々(週に1度程度)発生します。
  • 具体的にはファイルを変更したのに変更差分が認識されない(特にスクリプトを外部ツールでマージした際に顕著に発生)、updateしたのにローカルのファイルが古いまま、Historyから復元しようとしたら復元元のディレクトリが無いとか言われて復元できなくて死亡して愚痴愚痴愚痴愚痴愚痴...
  • 大人数で使うことを開発元が想定していないフシが多々あって、一番わかり易い例が最大同時接続数。これ最初の設定だと20人が限界です。PostgresのデフォルトがTCP接続40本までで、Asset Server Clientは1クライアントあたり2本TCPを貼るので。更に悪いことにこの設定を変更するにはPostgresSQLの設定ファイルを自分で操作する必要があります。簡単だからという理由で導入してここで躓いたチームは地獄を見る(むしろほぼ解決不可能になる)ことになります。
  • ところどころ完成度の低い機能があったりします。例えば既存リポジトリのコピーが可能なんですが、誰か一人でもどこかのリポジトリにクライアントが接続していたらコピーが出来ないと言われてしまいます。・・・えーと、全員帰った後にコピーしてくださいってことでしょうか><

■結論

Unity Asset Serverは、状況次第では非常に強力な選択肢になりえます。例えばチームメンバーのほとんどがバージョン管理システムを使ったことがないとか、グラフィックやサウンド担当の人が多くて彼らがSubversionやgitを覚えるのは不可能というとき、社内でSubversionやgitのサーバーを運用するノウハウがない少人数のチームのとき。こういう時にはAsset Serverの導入しさえすれば誰でも使える簡単さが大いに役立ちます。

しかしながらこの内容で1ユーザー5万円という値段はどう考えても暴利と言わざるを得ません。またできることが浅く、機能が少なすぎる弊害が簡単さによる生産性向上度をだんだん上回っていきます。とくにJenkinsと組み合わせる際の相性の悪さが辛いです。シーンやプレファブのマージができるのであればまだ5万円の価値はあったのですが・・・ということで、すでに他のバージョン管理システムを使えているチームでしたら、ぶっちゃけそのバージョン管理システムを使ったほうが良いと思います。


■こぼれ話

Unity Asia Bootcamp Tour東京で聞いた話など。まずGREE(というか@splhackさんの部署)はバージョン管理にgithubを使っているそうです。gitでは無理だと思っていたのですが、チーム全体の習熟度が高ければ問題なく回せるものなのかと感動しました。それからUnity Japanの大前さんにUnity Asset Serverに関する不満を申し上げたところ、やはりUnity側でもそのあたりは問題点として認識されているとのことでした。改善に期待するしかないですね><

2012年4月15日日曜日

iphone_dev_jp 東京iPhone/Mac勉強会でしゃべってきた & 反省

昨日開催されましたiphone_dev_jp 東京iPhone/Mac勉強会で1セッションほどお話しさせて頂きました。
http://atnd.org/events/26946

当日の様子がニコ生で配信されていて、現在タイムシフトで視聴することができます。一週間視聴できるので、4/20までですかね。
http://live.nicovideo.jp/watch/lv88663921

このタイムシフト視聴であとから録画されたプレゼンが見られるというのが実に素晴らしくて、具体的には以下のようなご利益があるわけです。
  • 遠隔地の人(今回は大阪の人)が同時に勉強会に参加できる
  • 参加できなかった人があとから当日の雰囲気を見るのに使える
  • 発表者があとから自分のプレゼンを見て反省するのに使える
主催していただいた岸川さん、機材を準備していただいたshachiさんをはじめ運営の方々、ありがとうございます!この仕組が他の勉強会でも流行ればなぁとか思ってます。(自分で主催する気がなくてすんません><)

さてここからは反省会です。タイムシフトのお陰で普段できない「自分のプレゼンはどんな具合だったか」をあとから客観的に見直すことができるので、これは大いに捗るぞと思いちょっと見てみました。2時間30分ちょいぐらいから出てくる一番煩いのが私なのですが。

うん。これはひどい><
ともかく、悪かったところとまぁ良かったんじゃないってところを列挙してみます。
  • 喋るの早すぎ。テンションが上がると更に早くなって困る。
  • 落ち着きなさすぎ。動きがなさすぎるのもつまらないので動くの自体は良いと思っているけれども、動きに変な癖があってそれが煩い。
  • プレゼンの資料で前提知識というか説明が抜け落ちている箇所が多々ある。急ぎで作ったBlocksの資料とかが顕著で、なぜ最初にアプリをクラッシュさせてるのとか説明がない。唐突すぎる。
  • 超テンションで超フランクにやったおかげかツッコミがいただけた、ネタ議論っぽくなったのはすごく良かった。だが、うまく広げられてないのがもったいない。テンパりすぎ。
逆にプレゼンが非常にうまかったsonsonさんやfladdictさんのプレゼンを見て、自分のプレゼンと比較して気づいたところを列挙してみます。
  • 発表に安心感というか安定感というか落ち着きがある。このあたりは場慣れしていきたい。
  • 図の使い方、図による説明の仕方が上手い。直前まで作っていたとか手書きで仕上げたのはやっぱダメですね><
  • デモの回数・実施方法が適切。最もキモとなる1回か2回程度に抑え、あまり資料から離れないため、流れが中断されない。ちょっと自分のプレゼンはコードとデモに逃げすぎたため流れが悪くなっていた。必要であればコードは資料の方に書いておいて流れを切らないようにする(要するに手抜き資料を作ってはならない)

あとはこれを踏まえてどんどん場数を踏んで上達していきたいですね。ということでiOSの勉強会とかで発表者募集している方がいらっしゃいましたら是非宜しければ喋らせてください!

2012年3月17日土曜日

非同期で動作する OCUnit (SenTestingKit) を書いてみた

非同期のテストができないのでGHUnitを使っていたのですが、やっぱりCmd+U一発で単体テストが走る便利さがいいなーと思い、ためしにSenTestingKitで非同期のテストができないかやってみたらできちゃったので公開します。

https://github.com/akisute/SenAsyncTestCase

ライセンスはMITライセンスとします。

使い方とか例とかはREADMEを見たりテストケースを見てみたりしていただければ一発でわかるかと思います。あ、もちろんSenTestingKit.frameworkが必要ですよ。