2008年12月17日水曜日

CS193P 11日目 非同期処理をやってみる

  • 非同期処理を行う方法はいくつかある
  • URLフェッチ処理ならば、NSURLConnectionクラスをつかっておけば一発
  • さらに簡単にURLフェッチ処理を行いたいのであればこのライブラリをおすすめ
  • URLフェッチ以外の処理を行うならば、NSThreadを使うか、NSOperationとNSOperationQueueを併用する
  • NSThreadは従来どおり、本当にスレッド処理を記述する必要があるため非常に大変
  • 対するNSOperationはインスタンスをつくってキューにぶち込んだら後は勝手にやってくれる、楽
  • UIViewやUIViewControllerに対する処理(要するに画面に対する処理)は、必ずメインスレッドから呼び出す必要がある
  • スレッドセーフではないため
  • 要するに[object performSelectorOnMainThread:withObject:waitUntilDone:modes:]を使えば解決する

いきなり日付が飛んで11日目です。
このあたりからは課題1つにつき3日分ぐらいのの講義内容が含まれていて、難易度がどんどん高くなってきました。
母さん、おいらスタンフォード大学の学生にはなれそうもないよ。



さて、今回の内容は非同期処理です。
現在の課題ではTwitterのタイムラインをJSON形式で取得して表示を行っているのですが、
メインスレッド(プログラムのメインループが走っているスレッド)の上から直接URLに対してHTTPアクセスを行っているため、
処理が返ってくるまでメインスレッドがブロックされ、結果フリーズしたように見えるという問題がありました。
これを非同期処理にしてブロックしないようにしましょうね、と言うのが今回の課題の内容。

NSURLConnectionと言うクラスを使えばURLのフェッチを自動的に非同期で行ってくれるのですが、
ご丁寧に「NSThreadかNSOperationで処理してね」とご忠告が。
Threadはどうにも使いこなせる気がしないので、ここはより簡単なNSOperationを使おうと思います。
(ゲームなどではおそらくNSThreadを使うことになるんだと思いますが)


NSOperationというクラスを継承して、
mainメソッドをオーバーライドして処理を記述し、
NSOperationQueueに追加すると自動的にThreadを裏で立ち上げて並列処理を行ってくれます。
処理が完了したらKVOという機能を使ってNSOperationから通知を受け取るらしいです。
しかしこのKVOと言う概念がイマイチ理解できないので後回しにして、
より簡単なNSInvocationOperationというクラスを使うことにしました。

使い方はこんな感じです。
NSInvocationOperation *op = [[NSInvocationOperation alloc]
     initWithTarget:self
     selector:@selector(reloadPerson:)
     object:person];
 [self.operationQueue addOperation:op];
 [op release];

これだけで自動的に並列処理をしてくれるんだから凄いと思います。
ということで、今回の課題では以下のように並列構成をしてみました。

スレッド1:メインスレッド
スレッド2:TwitterからTimelineを取得するためのスレッド(NSInvocationOperation + NSOperationQueue)
スレッド3:画像を取得するための並列処理(ImageStoreを利用、内部的にはNSURLConnection)

ところがこれがうまくいきません。
1と2だけを並列処理させたときはうまくいき、1と3だけのときもうまくいくのですが、
1と2と3と並列で動かすとエラーになります。
ああもう!だから並列処理なんて嫌いだ!

デバッガで調査してみるとSocketの取得のあたり?でとまっている感じがしたので、
スレッド2かスレッド3がソケットを捕まえてロックしているのではないかと考え、
使ったらすぐreleaseするようにソースを変えてみたのですが、効果なし。

Google先生にご相談したところ、それらしい回答が。
【iPhone】スレッド中で[UITableView reloadData]を使ってはいけない
なるほど!自分のソースを見直すと、確かにスレッド2の処理の中でUITableViewに対してreloadDataを呼び出しています。
さっそくご指摘のあったとおりにソースを書き直してみました。
if ([delegate respondsToSelector:@selector(mPersonDataSourceDidFinishLoadOfPerson:)])
{
 [delegate performSelectorOnMainThread:@selector(mPersonDataSourceDidFinishLoadOfPerson:) withObject:person waitUntilDone:YES];
}

今度は一発で成功!

2008年12月14日日曜日

第2回 Google App Engine Hackathon

  • 今回で第2回目
  • 主催は@tmatsuoさん
  • 4チーム(内部でさらに分かれるため合計6チーム)に分かれて作業をし、最後に発表する形式
  • 1回目よりも運営が格段にスムーズで素晴らしい時間を過ごせた
  • GDataの認証はすさまじく難しい。またGDataアクセス用のライブラリがあるが、これまた非常に機能が多く難しい
  • Google App Engine Oilは凄く良い、余計なことをしないし必要な者は全部作ってくれる
  • gaeogenはバージョン0.21の地点ではバグがあるためまともに機能しない
  • DropBoxを使ったグループ開発はすさまじいスピード感がある

http://groups.google.co.jp/group/google-app-engine-japan?hl=ja
ちょっと遅くなりましたが、2008年12月13日に開催されました第2回 Google App Engine Hackathonについてご報告です。

主催は前回に引き続きGoogleの認定エキスパートである@tmatsuoさん。
前回は好き勝手にGAEで物を作るだけという感じだったのですが、今回は趣向を変えて、
  • チュートリアル:RSS Reader作成
  • チュートリアル:Twitterもどき作成
  • GDataを用いたマッシュアップ:Bloggerなどとマッシュアップする組
  • GDataを用いたマッシュアップ:Picasaなどとマッシュアップする組
  • フレームワーク
  • データモデル
以上の6組に分かれてそれぞれ活動し、結果を最後に発表すると言う形式で行われました。
目標がはっきりしていたおかげで、最後にはものすごいアプリが次々飛び出しました。大成功だったと思います!
運営の皆さんありがとうございました!
前回に引き続きお弁当おいしかったです =)


詳細につきましてはHiiroさんのブログをご参照ください。
Hiiro_memo: GAEハッカソン参加感想&まとめ:Google凄いが周辺人も凄い


私はマッシュアップ班に参加いたしました。
ちなみに隣の席が世界に名だたるおっぱいプログラマー@technohippyさんでした。びっくりです。
Da変態な人かと思っていたら、意外と普通の人でした。Vistaに泣かされていましたけど。

今回のマッシュアップ班の開発の際には、DropBoxに全員のプロジェクトファイルを配置して、いつでもみんなのファイルを参照できるようにして作業しました。
コレが凄くいいです。誰かが一人難所をクリアできれば、すぐにみんながそのソースを参照して動かせるように出来たため、作業効率が格段に良かったです。
(共有する人はコミット作業すら必要ありません。全部自動的に同期してくれるから)

さっそくDropBoxが大のお気に入りになりました。Windows機にはあまり導入したくなかったのですが、
こんなに便利なら使うしかないですね。


また、噂のGoogle App Engine Oil(GAEO)も試してみました。
gaeo testproject

とすると、testprojectを作成してくれるのですが、コレが素晴らしい!
最初から絶対に必要になるjs, img, cssフォルダを作成してくれたり、faviconの設定もしてくれたり、かゆいところに手が届く感じです。
RequestHandlerの実装も非常に簡単になっていて、
class WelcomeHandler:
  def index(self):
      #get All models from DataStore
      models = AModel.all().fetch()
      #set models to self object to use it when rendering the template
      self.models = models

たったのこれだけで、テンプレートのレンダリングまで全部自動でやってくれます。

本当はgaeogenというrailsのscaffoldのような機能があるのですが、こちらは0.21の段階ではバグがあるようでまともに機能しませんでした。
(ソースを参照したところ、argvに対してgetメソッドを呼び出したりしていました。
Pythonのargvはlist型だからdict型にしか使えないgetメソッドは利用できないです)
でもgaeoだけでも十分すぎるほど便利ですから導入する価値は有りだと思います。

2008年12月6日土曜日

CS193P Cocoa Programming - ソースコードをgithubに公開いたしました

gitの練習もかねてここまでの成果ソースコードを公開してみました。
http://github.com/akisute/akisute_cs193p/tree/master

特に見所はありませんが、一応自分の勉強用として。