投稿が1千件くらいになると無制限にリストアップというわけにはいかなくなるわけでして…
 対策として一般的なのが、アメブロがやってるようなページング処理なわけです。

$テン*シー*シー-1

 ↑こんな感じで記事を何件かの単位でページに分けて表示してる。
 次のページや前のページに戻るためのボタンを用意してページを切り替えるわけですな。

 で、もう少しiPhoneらしいアプローチが、YouTubeなんかでやってる最後の行に「さらに読み込む…」って項目の表示。こいつを押すと行が追加される仕組みなわけです。

$テン*シー*シー-2

 十分に直感的でナイスなんですが、こいつのさらに上をいく直感的なGUIをTwitter用iPhoneアプリのTwitBirdで発見したんですよ。

$テン*シー*シー-3

 いや~、ナイスです。
 こいつは更新側だけど、最下部の項目までスクロールしてさらに引っ張ると、同じように追加の項目が読み込まれます。
 スクロールバウンズ機構をうまく利用して「まだ、他にあるんじゃない?」ってテーブルの外側を見ようとする心理と「更新」機能がベストマッチ。

 しかも、不用意に更新しないようにある程度引っ張らないと実行されないし、手を離すまでは引っぱり量によって、上の絵の赤丸で囲った矢印が反転したり、注意書きが「プルダウンで更新」と「手を離すと更新…」と変わるので、「更新」するかしないかを指定もできるという…

 いやいやいや~、ツールバーに更新ボタンがあるんで、あくまで予備機能として用意されてるみたいですが、感動的です。

 どうやったら実現できるか興味わきません?
 私はわきました。

 ちゅ~わけで、TwitBirdっぽい更新機能はどうやって実装するのか調査してみた。

 まずはスクロールできるよう10項目程度のテーブルを用意。
 このやり方は、この前テーブルとナビゲーションを理解する(1)を書いたので省略。わからん人はそっち参照してね。
 スクロールでテーブル外にビューを表示するにはどうするかなんですが、これは簡単でした。
 RootViewController(Xcodeテンプレートのままという前提)のviewDidLoadメソッドで
- (void)viewDidLoad {
[super viewDidLoad];
CGRect r = self.tableView.bounds;
r.origin.y -= 40;
r.size.height = 40;
triggerHeader = [[UILabel alloc] initWithFrame:r];
triggerHeader.text = @"更新";
[self.tableView addSubview:triggerHeader];

}

 こんな感じでテーブルビューにビューを追加するさいに、あえてbounds外に配置することでスクロールバウンズ時に表示されるようになるわけっす。

$テン*シー*シー-4
あくまでUITableViewのサブビューとして追加するが、場所はUITableViewのbounds外とする

 ぐいっとひっぱると、triggerHeaderビューがちらりと見える。

$テン*シー*シー-2

 で、UITableViewControllerが継承してるUITableViewDelegateプロトコルはUIScrollViewDelegate プロトコルを継承してるので、scrollViewDidScroll:メソッドを実装するとスクロール中に呼び出してもらえるわけで…
 triggerHeaderビューに以下のように現在のテーブルのboundsを表示させるように実装すると…
- (void)scrollViewDidScroll:(UIScrollView *)scrollView { // any offset changes
CGRect r = self.tableView.bounds;
triggerHeader.text = [NSString stringWithFormat:@"%lf", r.origin.y];
}


 こんな感じで座標が逐次変化してるのがわかる。

$テン*シー*シー-6

 で、こうなりゃしめたもので、座標がある一定の値よりも小さくなったら引き金が引かれたとみなしたらいいわけです。

$テン*シー*シー-7

 今回は、貼付けたUILabelの中にUIImageViewを貼付けておき、こいつを引き金の状態にあわせて回転させてみます。
- (void)viewDidLoad {


// トリガーのイメージを埋め込むtriggerHeader
UIImageView* imageview = [[UIImageView alloc]
initWithFrame:CGRectMake(100, (40 - 16) / 2, 16, 16)];
imageview.image = [UIImage imageNamed:@"arrow.png"];
imageview.tag = 1;
[triggerHeader addSubview:imageview];
[imageview release];
headerOn = NO;



 imageview.tag = 1;としてるのは、後でimageviewをtriggerHeaderから探し出せるように。インスタンス変数として持ていてもかまわないんだけど、めんどくさかったので…
- (void)scrollViewDidScroll:(UIScrollView *)scrollView { // any offset changes
CGRect r = self.tableView.bounds;
triggerHeader.text = [NSString stringWithFormat:@"%lf", r.origin.y];
if ((r.origin.y < -50) && (headerOn == NO)) {
headerOn = YES;
UIImageViewがひっくり返る回転アニメーション開始
}
if ((r.origin.y > -50) && (headerOn == YES)) {
headerOn = NO;
UIImageViewが元に戻るアニメーション開始
}



 で、UIImageViewがひっくり返る回転アニメーションてのはこんな感じ。transformその(37)で説明してるアニメーション指定ができる属性です。180度の回転行列を渡しとります。回転行列~な人はその(64) あたりを…、う~ん、あんま説明になってないか…その(91)でまじめに説明しようとしてるんだけど、まあ、がんばって自力でなんとかしてください。

UIImageView* imageview = (UIImageView*)[triggerHeader viewWithTag:1];
[UIView beginAnimations:nil context:nil];
imageview.transform = CGAffineTransformRotate(
CGAffineTransformIdentity, 3.14);
[UIView commitAnimations];


 これで、triggerHeaderの表示が-50を超えるまでひっぱると…

テン*シー*シー-8

 くるりんぱっ

テン*シー*シー-9

 TwitBirdぽく動くわけです。
 で、ヘッダーは簡単だけどフッターはちょっと問題あり。
 というのもテーブルのboundsは見えている部分の大きさでしかないんで、どの座標がテーブルのお尻なのか決めるのに計算が必要で、しかも項目が追加されたり削除されたりするごとに位置を再設定しないと駄目なんですな。
 どうやって解決するかというと、とりあえずtriggerHeaderと同じ要領でtriggerFooterってUILabelインスタンスを作ったとして
self.tableView.tableFooterView = triggerFooter;

 って感じで、テーブルのフッターにしちゃいます。
 これで項目が追加されたり削除されたりするごとにおこなう位置調整はUITableViewにお任せできるわけです。
 あとはscrollViewDidScrollメソッドでtriggerFooterのframeの底辺を、現在のUITableViewのboundsの底辺が一定値以上超えてれば引き金を引くようにすれば完成です。
 作業としてはviewDidLoad、scrollViewDidScroll:メソッドに集中してるので、詳しくはサンプルソースをみてちょ。

------------
サンプルプロジェクト:Scrollout.zip