なんかしゃべれと言われたので、 Mitaka.rb #4 に参加してきました。フレンチうまうま。
るりまふぉん、という内容で話してきました。読んで字のごとくですが、るりま を iPhone から見れるようにする何かをつくったよ、という話です。
るりまふぉんのソースは こちら : github:mootoh/rurimaphone。
一昨日に、 Mitaka.rb の用意してないやん、そういえばさいきん Ruby さわってないやん、と気づいてあわててネタをひねりだし、昨日一日でプロトタイプをつくったかんじのものです。
スライドの余談のところにも書いてありますが、 Ruby で書いたコードはほんの少しで、ほとんどは Objective-C のコード。
Future Work に書いたことは割と本気で考えていることで、どこでもプログラミングできる環境というのができてきてると思っているのです。 iPhone だと、任意のコードを実行できるアプリはダメなんだけれど、あちら側にあるソースを、あちら側で実行して、あちら側にある実行結果を見るだけならば、別に問題なかろうと。クラウドとはいえないけれどそういうもの。それは gist と tryruby 的なものを組み合わせればできるんじゃなかろうかと。
もうひとつは、 サンプルコードを共有できるマニュアル という話。こっちの方が元からあったアイデア。
プログラミングをじっさいにやっていく中でだいじなのは、サンプルコードとコミュニケーションかなと。
マニュアル読んでて、じゃあじっさいにどういう風に書けばいいのん、という段になって困る、というのがよくあります。 Ruby だと、拡張ライブラリの rdoc ドキュメントを読んでるときによくそういう状態になったりする。
そんなとき、みんなが持ち寄ったコードを見ながら書き進められるといいんじゃないでしょうか。そのために、みんなでそのクラス、メソッドに対するサンプルコードを共有できるといいのではなかろうかと。 Wiki 的なアプローチというか。
んで、なんか困ったことがあったらビルトインの Twitter / IRC で質問を投げたりできると。
ちなみに iPhone はキーボードがないのでコード入力するには適さないよ、という意見もあるでしょうが、そこは補完入力とか音声認識とかいろいろやり方はあるはず。そろそろ外部機器も使えるようになるはずだし。
そんなこんなで、 iPhone で Ruby な何かをやりたい方は % git clone github:mootoh/rurimaphone してみたらいいんじゃないの、というお話でした。
フレンチおいしかったです。

そういえば、 Phonad という iPhone アプリをリリースしていました。ふぉなど。
何ができるかというと、 iPhone のアドレス帳を電話番号から引く 、というそれだけのものです。それしかできない。
iPhone も 3.0 になって Spotlight 検索ができるようになったのですが、この 電話番号からアドレス帳を引く 、という単純なことがまだできずにいて、そこを解決するためのアプリです。一見ニッチ。
なぜこんなアプリをつくったか。義理の兄がさいきん iPhone ユーザになりました。で、なにか欲しいアプリってないですかねー、と聞いてみた。彼は営業のしごとをしており、あちこちに電話をするわけです。仕事に関係する電話についてはお金が出る。仕事でもプライベートでも同じ電話をつかっているので、通話明細から仕事についての電話だけを拾いださないといけない。ところが iPhone だと電話番号からそれが誰かを引けない… というストーリーでした。
これまで iPhone 的なものに馴染んでないユーザのひとたちから何が足りないかを聞いてまわるのはだいじですね。なにがニッチなのかは見る立場で変わる。
Google Calendar や Remember the Milk といった Web サービスには、 SMS 通知という機能があります。指定しておいた時間にリマインダがケータイに飛ばされてくるやつですね。
ところが、これまで iPhone で SMS を通知を受けようにもやり方がわかりませんでした。ユーザ名 at i.softbank.jp という選択肢が、 Web サービス側になかったのです。1
しかし、 iPhone OS 3.0 で MMS を送受信できるようになり、状況がかわりました。やってみてうまくいったのでシェア。
MMS
Softbank での MMS アドレスは ユーザ名 at softbank.ne.jp になります。これは、 Remember the Milk などの Web サービスでも選択肢にあります。
Remember the Milk での設定は、 “Settings” → “Reminders” (このアドレス) で、設定例は以下のようになります。

iPhone での MMS 通知をメール通知と比べたときの利点は、どのアプリにいても、通知内容がプレビューつきで、ポップアップ通知される ところですね。いわゆる Push Notification です。これがかなり便利。
iPhone アプリ側で Push Notification を実装するのも手なのですが、 MMS という既に Push Notification の共通基盤として存在するものを使うというのもアリかなーと。たとえば、ぼくのつくっている Remember the Milk の iPhone クライアント Milpon でも Push Notification やろうかなーと思ってたんだけれど、 MMS 通知で狙っていたことが十分に達成できてしまっていました。
他にも SMS 通知してくれる Web サービスってありますかね?
あと料金ですが、ソフトバンクに問い合わせたところ、海外からのでも MMS の送受信は パケット定額フル の適用範囲内とのことでした。受信料を気にせずじゃんじゃん MMS 通知を受けまくって OK ですね。
iPhone アプリをつくってて、 Bonjour をつかえばいろいろと楽しいことができるんじゃない? と調べていました。ここまでのところをシェア。
Bonjour というのは、 DNS サーバがなくても、同じネットワーク内にいるコンピュータを見つけあうことができる技術。 Zero Configuration とか Rendezvous とか言われてたりもした。
準備
遊びでつかうなら、 service type = _wwdcpic あたりでローカルで遊ぶといいんじゃないかな。
本気でつかうなら、dns-sd にサービスの登録をする。
サービス名、説明、責任者といった情報をつけてメールすれば、そのうち受理されたりする。
Cocoa API
いいところ:
- 使いやすく抽象化されてる
- Mac, iPhone どちらでも同じように使える!
ちゃんと RubyCocoa でも使えたよ!
NSNetService
サーバ側。サービスを提供していることをアピールし、クライアントから接続されてくるのを待つ。
ながれ:
- initWithDomain_type_name_port
- setDelegate
- publish
ここの type で指定するのを、 dns-sd に登録しておくということ。
クライアントとのやりとりは delegate のコールバックに通知される。
接続されたあとの処理は、ふつうのネットワークプログラムとおなじ。
NSNetServiceBrowser
クライアント側。サーバをてきとうに探し出して、接続する。
ながれ:
- init
- setDelegate
- searchForServicesOfType
みつかったあとのサーバとのやりとりは、 delegate のコールバックに通知される。
Sample code
/Developer/Examples//Foundation/PictureSharing
このコードを読むと、だいたい把握できる。
あと、自分で書いたコードが github:remoteshortcuts にあります。 Mac with RubyCocoa, iPhone とごちゃまぜなかんじがたのしいかと。
つまづきポイント
- NSNetService は、 stop を送られたあとにもう一度 publish で起動しようとしてもダメ (しぬ)
- delegate を設定する前にメッセージを送っても意味なし
まとめ
想像以上にかんたんに使えました。 Cocoa フレームワークはすばらしい。
iPhone アプリどうしで小さなネットワークをつくって遊ぶようなときにさくっと使うと楽しそうです。勉強会とか。
Milpon 2.0 が AppStore にでました!

UI の大幅な改善、タグのサポート、 URL がついてるタスクは内蔵ブラウザで表示、タスク名やリスト、ノートを変更できるようにした、などなどたくさんの変更が入ってます。しかも無料! (ひきつづき)
かれこれ4ヶ月をかけたアップデートになっています。
いろいろ見てたところ、無料で RTM と同期できる iPhone アプリはないとか。ぜひおためしください。
今後のアップデート予定は、
- 週次レビューの支援
- “あとまわし” ボタンの追加
- スマートリストのサポート
- 日本語へのローカライズ
- 高速化
などがあります。こちらもおたのしみに。
しばらく音沙汰がない間なにをやっていたかというと、ずっと Milpon の次期バージョンをつくっていました。
UI の再構築、タグのサポート、などたくさんの改善をおこなっています。
App Store にアップグレードを申請中です。近いうちにリリースされるといいな。
スクリーンショット
Overview で時系列に、List でカテゴリごとに、 Tag でそれぞれを横断してタスクを一望できます。

完了ボタンをやや大きくして、押しまちがいの少ないようにしました。

タグでタスクを整理しているところ。

タスクの詳細表示の画面で、タスクの属性をよりいじれるようにしました。

id:KishikawaKatsumi さんによる、カレンダーで日付がえらべるようにするコードがはいっています。

タスクの追加画面。おおきめの表示にしました。

自分でも 2.0 をつかってフィールドテストしているのですが、もう 1.0 には戻れませんね。
App Store にでるまで、いましばらくおまちください。
ToddleDatabase という SQLite3 のラッパーライブラリを github に置きました。 iPhone での SQLite3 をつかった開発を多少ラクにするためのものです。 Milpon の beta07 からつかっています。
例: SELECT
例として、 (id, name, tag_id) というフィールドからなる table から、指定した tag_id をもつ (id, name) をひっぱってくることを考えます。
ベタに SQLite3 の C API をつかうと以下のようなかんじ。
/*
* collect (id, name) pairs from 'list' table by tag_id.
* table 'list' consits of (id, name, tag_id)
*/
void select_list(sqlite3 *handle, int tag_id)
{
// construct query
sqlite3_stmt *stmt = nil;
const char *query = "SELECT id,name from list where tag_id=?";
if (sqlite3_prepare_v2(handle, query, -1, &stmt, NULL) != SQLITE_OK) {
handle_error([NSString stringWithFormat:
@"Error: failed to prepare statement with message '%s'.",
sqlite3_errmsg([db handle])]);
return;
}
sqlite3_bind_int(stmt, 1, tag_id);
// send query and collect results
while (sqlite3_step(stmt) == SQLITE_ROW) {
NSNumber *iD = [NSNumber numberWithInt:sqlite3_column_int(stmt, 0)];
NSString *name = [NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, 1)];
}
sqlite3_finalize(stmt);
}
これ1つだけならいいんですが、アプリ内にこれと同じようなコードブロックが散在するのが悩みのタネでした。共通化しようにも、query として渡す引数の数はいくつになるかわからないし、型も不定。query の実行結果についても同様で、うまくまとめられません。
ToddleDatabase をつかうと以下のようになります。
(NSArray *) select_list:(ToddleDB *) db withTag:(NSNumber *)tag_id
{
NSDictionary *where = [NSDictionary
dictionaryWithObject:[NSString stringWithFormat:@"id=%d", [tag_id intValue]]
forKey:@"WHERE"];
NSArray *keys = [NSArray arrayWithObjects:@"id", @"name", nil]; // fields of table
NSArray *types = [NSArray arrayWithObjects:[NSNumber class], [NSString class], nil]; // types of each fields
NSDictionary *query = [NSDictionary dictionaryWithObjects:types forKeys:keys]; // run SQL SELECT
return [toddleDB select:query from:@"list" option:where];
}
かんたんですね!
抽象化したことでどれくらいパフォーマンスに影響が出ているかは、まだ計っていません。どうだろうかな。
アプリケーションのプロトタイピングにはこういうラッパーを使ってじゃっかん抽象度の高いレイヤで試行錯誤し、リリースするにあたっては SQLite3 API を直叩きする、というのがベストプラクティスなのかな。
もっとよい抽象あるよ! とか高速化のヒントなどあれば、ぜひぜひ fork するなりコメントなりでお知らせください。
Remember the Milk の iPhone アプリ、 Milpon をリリースしました。
ダウンロード
iTunes App Store でひらく
今後
けっきょく、ここまでくるのに半年ちかくかかってしまいましたが、これからも開発を続けたいと思っています。機能的にも使い勝手的にも、まだまだ満足のいくものではないですし。
とにかく、 UI をもっと自然なものにしなきゃ。いまのものは迷いがあちこちに残っているので、タスク整理する際の流れがよどんでしまいますね。
iPhone Human Interface Guideline もひととおり読んだことだし、しっかりと考えてレイアウトしていこうと思います。
ということで、まずは 1.0 をダウンロードしていただいて、オフラインでの高速なタスク俯瞰をお試しください。そしてアップデートをお楽しみに!
紹介していただいた方々
ありがとうございます!
Remember the Milk Blog :: New for Pro: Remember The Milk now available on the App Store
ついにきたっ! しかもおそるべきクオリティでっ!! 全俺涙目!!!
と5分くらいへこたれてましたが、Twitterでいろんな方に励まされたりして立ち直りました。みなさんありがとうございます。いいものをつくればいい。世界の見方は何とおりでもあるよ。
ということで、 Milpon はまだ開発をつづけていきます。現在はベータ03というフェーズにありますが、よりよいインターフェイスを求めてあがいていきます。
昨日ベータ版を公開した Milpon のソースコードをGithubで公開しました。ライセンスは修正BSDです。つっこみなど絶賛募集中。
XMLParser、SQLite、カスタムUITableViewCell、SenTestingKit をつかった単体テストのコード、といったあたりがごっちゃりと入っていますので、参考になればしあわせです。
実行するにはRemember the Milk の API キーが必要です。ご注意を。