2009年6月8日月曜日

時間を入力するために、カスタムUIPickerViewを作ってみた



時間を入力するためのUIが欲しかったので、こんな感じのカスタムUIPickerViewを作ってみました。ソースコードはこちら。
http://github.com/akisute/YourTurn/blob/8119bf028acf4908edb602d277544bc2cf6a5848/Classes/YTTimePickerView.h
http://github.com/akisute/YourTurn/blob/8119bf028acf4908edb602d277544bc2cf6a5848/Classes/YTTimePickerView.m


使い方はソースを見ていただければきっとご理解いただけると信じておりますので、UIPickerViewを使っていて気づいた点などをいくつか晒してみたいと思います。


■参考にした記事
id:paellaさんのダイアリーを参考にさせていただきました。ありがとうございます。
http://iphone-dev.g.hatena.ne.jp/paella/20090521#20090521fn1

基本的にはこちらの記事にまとめられている内容に従って、
// 2) ビューを返したい場合
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {}
このデリゲートメソッドを使いカスタムViewを利用した実装を行ったのですが、一部私の実装とpaellaさんの記事で異なっている点があるので、ご紹介したいと思います。


■UILabelを直接デリゲートメソッドから返す
元記事では、
UIViewを返すデリゲート、必ずUIViewを返さないとうまく動いてくれません。このサイトやこのサイトで紹介されているようなUILabelを直接渡してあげる方法は、少なくとも私の環境(2.2.1)では何も表示されませんでした。
と、UIViewを返さなくてはダメとご指摘がありますが、どうやらUILabelでも大丈夫みたいです。ビルドターゲット = iPhone OS 2.2.1の環境で確認できました。

UILabelをそのままデリゲートから返却したときに画面に表示されなかった原因は、どうやらUILabelのframe.size.heightが0になってしまっていた(要するにつぶれてしまっていた)のが原因みたいです。そこで、以下のようなコーディングを行いました。
- (UIView *)pickerView:(UIPickerView *)picker viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *label = (UILabel *)view;
if (!label)
{
label = [[[UILabel alloc] init] autorelease];
label.frame = CGRectMake(label.frame.origin.x, label.frame.origin.y, 20.0, 23.0);
label.backgroundColor = [UIColor clearColor];
// 以下初期化コードなど・・・
}

return label;
}
このように、label.frameの高さを無理矢理指定してやれば、きちんと画面に出せるみたいです。また、この方法を使えば、元記事で
ポイントはビューの座標。どうも各要素での{0,0}の位置はPicker内各Rowのど真ん中にあるらしく、サンプルのように負数を指定してあげないとどこかに寄った状態になってしまうみたいです。
とご指摘があったビューの座標も、特に気にせず普通に指定することが出来るようになりました。


■Pickerを、UIScrollViewのサブクラス(UITableViewなど)にaddSubviewする場合の注意点
この記事の見出しに貼り付けた画像では、作成したカスタムPickerをGroupedスタイルなUITableViewのfooterViewに貼り付けています。
    // Initialize time picker with a previously selected value
timePicker = [[YTTimePickerView alloc] initWithFrame:CGRectZero];
NSInteger initialValue = [[NSUserDefaults standardUserDefaults] integerForKey:_USERDEFAULTS_TIMEPICKER_INITIALVALUE];
timePicker.time = (initialValue == 0) ? 300 : initialValue;
timePicker.timePickerViewDelegate = self;
[timePicker selectRowWithCurrentTime];
self.tableView.tableFooterView = timePicker;
このように、UIScrollViewのサブクラスのサブビューとしてUIPickerViewを貼り付けると、そのままの状態ではうまくPickerのドラムが回転してくれないという症状が発生してしまいます。
これはどうやらUIPickerViewのスクロールとUIScrollViewのスクロールがけんかしてしまっているみたいです。そこで、スクロールする必要のないTableView側の設定をOFFにします。具体的には、Interface Builderを利用する場合、以下の赤枠でくくった箇所を設定すると良いようです。



こうすることで、綺麗にドラムが回転してくれるようになります。

2009年6月7日日曜日

java-ja #15 TDDとかペアプロとか

株式会社ドワンゴの本社にて開催された、java-jaの第15回勉強会に参加してまいりました。(ドワンゴさんありがとうございます!噂通りの社風が垣間見られておもしろかったです)
今回のテーマはTDDとペアプロ。TDDの権威である@t-wadaさん(http://twitter.com/t_wada)の講義+実際にTDD&ペアプロを体験する時間が設けられ、非常に充実した時間が過ごせました。

以下、Twitterにアップした感想を転載。


とにかく疲れる!そして慣れていないせいもあるがコードが進まない!普段の倍疲労して半分しかコードが進まないなら、明らかに生産性が下がっているように見える。でも違う、逆だ。こんなに生産的にコードが書けるとは思わなかった!

TDDを進めていくうちに、自分が意図しない考えや見落とし、typoなどの指摘が次々に飛び出した。書き上がったテストコードも普段自分が作っているものより綿密だ(もっとも普段はかなり手抜きなのだが)。TDDに反する進め方を指摘してストップすることもできた。

TDD自体はというと、テストケースが増えたり仕様が複雑化してきたりすると、途端に難易度が跳ね上がるな。一箇所直すと複数のテストがあっという間に真っ赤になる!新しくテストを作る判断とかも難しい、なによりテストを実行するのが面倒になったりする。jUnitMaxが素晴らしい理由を体感。

ペアプロの弱点は調べ物だな。明らかに調べ物をするときは個々人がググったほうが早い。だから熟練度が高くないとオーバーヘッドが大きくなってかえって非効率的。@yuruyoroさんには足引っ張って申し訳ない。スキルの差を埋める必要があるのも課題かなー、、、

個人的には一人でやる方が楽かな。人と話すのがへたくそ何だよなあ、、、いつもより疲れるのもそれが原因かも。ウォーターフォールがいけてないとはよく言うが、TDDやペアプロ自体にもたくさん課題があるのだなー、、、でも同じ課題満載なら、新しいやり方を開拓する方がいいよね、多分


TDDやペアプロは良いプラクティスですが、慣れないと実践は難しいですし、ウォーターフォールに代わる銀の弾丸でもなさそうです。そのことを実際に体で覚えることができたのが一番の収穫かな!

2009年6月4日木曜日

Firefox 3.5を導入してみた


いろんなところで話題になっている(http://d.hatena.ne.jp/chroju/20090523/1243076800)Firefox激重問題ですが、我が家でもニコニコ動画を見ることができないぐらい重くなっていたので、思い切って3.5b4を導入してみました。ちなみに、Mac OS X 10.5.7で試しております。


■利用したバックアップ用アドオン一覧など
Mozilla Re-Mix: インストールしているFirefoxアドオンをWeb上に保存してリストアできるアドオン「BELOW」
http://mozilla-remix.seesaa.net/article/109386090.html
Mozilla Re-Mix: Greasemonkeyスクリプトの利用環境をもっと便利にするFirefoxアドオン「Wescript」
http://mozilla-remix.seesaa.net/article/119556026.html
Mozilla Re-Mix: 拡張機能の「個別設定」をインポート・エクスポートできるFirefoxアドオン「OPIE」
http://mozilla-remix.seesaa.net/article/90165156.html
Mozilla Re-Mix: Firefox3 Beta版に対応していないアドオンを強引にインストールする方法。
http://mozilla-remix.seesaa.net/article/84338863.html


■インストール手順
1.AppCleaner(http://www.freemacsoft.net/AppCleaner/)を使ってFirefoxを完全に削除
  Windowsより消すのがラクチンです。

2.公式サイトから最新のbeta版をダウンロードしてきてインストール
  コピーするだけ。これも非常にラクチンです。

3.アドオンの復旧、まずはXmarks (http://www.xmarks.com/) をインストール
  ブックマークを最初に復旧します。

4.about:configを書き換えて強制的に古いアドオンをインストールできるようにする

5.ブックマークから、上記のバックアップ用アドオンを探してきてインストール

6.BELOWを実行

7.OPIEを実行

8.FireGesturesの設定が正しく復旧されていないので、手で復旧

9.Tab Mix Plusの設定が正しく復旧されていないので、手で復旧

10.Tab Mix Plusがバグっていることが判明したので、開発版 (http://tmp.garyr.net/dev-builds/) をインストール
   具体的には最後に閉じたタブが開けませんでした。
   Tab Mix Plusは大体バージョンあげるたびに問題が出るので、このサイトを覚えておくと便利。

11.Firefox自体の設定を調整

12.Wescriptを実行

13.自作のGreasemonkeyスクリプトをインストール


以上です。作業時間は40分程度でした。BELOWとOPIEは極めて便利なので本当にお勧めです。


■で、何が変わったか
正直、見た目はFirefox 3.0と全く変わりがありません。見た目で変化がわかるのはロケーションバーぐらいでしょうか。



動作はというと、まず例のニコニコ動画がガクガクして全く見られない問題は解消しました。動画を見ているときのCPU使用率も、前は2コアとも40〜50%程度消費していたところ、16〜20%程度まで低減しています。どうやら中身はしっかり改良されているみたいです。

いちばん大きな変化はリリースノート(https://developer.mozilla.org/Ja/Firefox_3.5_for_developers)を見ても分かるとおり、HTML5サポートだと思います。videoタグやaudioタグを利用できるようになったそうです。

早速試してみました。
http://www.youtube.com/html5


・・・動かないじゃないか!!><
(ちなみにSafari 4 betaでは動きます)

おそらく使われているビデオの形式がmpeg4なのが原因だとは思いますが・・・
変な青い枠が出ているのも、おそらくGoogleの中の人がChrome (Webkit)でしかテストしていないからでしょうし。
しかし、うーん、まだまだ開発版って感じがします。


■気になるアドオンの動作状況
微妙にTab Mix PlusがBuggyです。閉じたタブの履歴を正しく保存してくれていない感じがします。その他AdblockやFirebugなど、メジャーどころはほとんどすべて入れていますが、まだ1日も使っていないので何とも言えません。