iOSのUITableViewのAPIは結構よくできているので色々な事が行えます。
UITableViewの基本的な事は下記の記事を読むといいでしょう。

また、UITableViewで表示するUITableViewCell(セル)はデフォルトで幾つかスタイルを持っていて、
シンプルなデザインならばこのプリセットを利用すればわざわざカスタムセルを使わなくても問題ありません。

プリセットのデザインでは目的を達成できない場合は、UITableViewCellを継承したカスタムセルを作成することになります。
(UITableViewControllerでCellにaddSubView:するのは避けるべき事だと思うので、カスタムセルを作っていく方がいいと思います)

この辺の使い分けについてはiOSアプリ開発のプラクティスを適当にまとめているios-practiceの、
UITableViewについて — ios-practice 0.1 documentationで書いてあるので、こちらも読んでおくといいです。

カスタムセルについて

カスタムセル(UITableViewCellを継承したクラスのこと)は、通常のViewと同じくコードで書いていく方法と
Interface builderを使ってカスタムセルのxibを作ってやる方法があると思います。

カスタムセルの見た目を作るのはxibで十分な場合が殆どで、コチラのほうが作成も楽なのでInterface builderで作る方法の解説です。
基本的な作り方は下記で説明されている通りなのです。

以下に2種類のカスタムセル(アクションの付け方が違うだけでセルの作りは同じ)を作ったサンプルプロジェクトを置いてあるので、
これを例に見ていきます。

1. xibファイルの作成

どちらも xibファイルとUITableViewCellのサブクラスからなるカスタムセルで、xib的な作り方は同じなので、まずSmartCellの方を見ていきます。


@interface SmartCell : UITableViewCell{}

@end

といような、UITableViewCellを継承したサブクラスを作成したら、
New FileからEmptyを選んで、同じ名前( SmartCell.xib ) のxibファイルを作成します。

Xcode

TableView Cell のオブジェクトを配置したら、TableView Cell のオブジェクトのClassにはSmartCellを指定しておきます

SimpleCustomCell xcodeproj  SmartCell xib

後は普通をInterface Builderを使って任意のセルデザインを作成します。

2. UITableViewControllerからカスタムセルを利用する

次に作成したカスタムセルを、通常のUITableViewCellの代わりに使用するようにコードを書きます。
カスタムセルを使う方法はいくつか(毎回UINibから取り出したインスタンスを利用するや、UIViewControllerから取り出すなど)ありますが、
iOS5からならregisterNibを使うことで、一度xibを登録して置くのが簡単です。


- (void)viewDidLoad {
    [super viewDidLoad];
    // DataSource init
    // iOS5からは最初に一度だけnibファイルを登録すればいい
    [self.tableView registerNib:[UINib nibWithNibName:@"SmartCell" bundle:nil]
        forCellReuseIdentifier:kCellIdentifier];
}
// セルの作成delegate
- (UITableViewCell *)tableView:(UITableView *)tableView
                     cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *cellIdentifier = kCellIdentifier;
    SmartCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (!cell){
        cell = [[SmartCell alloc]
                           initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }

    // ….

    return cell;
}

また、iOS6 UITableViewのセルの再利用の方法が変わったりしていますが基本的な形はあまり変わらないので、
現在はregisterNibを使った方法がいいかと思います(iOS4も対応する場合はこの方法は使えないのでちょっと面倒ですが)

これで、カスタムセルを表示することができました。
(セルの表示を更新するメソッドを分離したり、細かい作法についてはUITableViewについて — ios-practice 0.1 documentationに書いてあるので省略しています。)

NewImage

3. カスタムセル上のボタンアクションをつける

サンプルazu / SimpleCustomCell にはEmbedActionCellとSmartCellの2種類のカスタムセルが置いてありますが、
この2つの違いはカスタムセル上に載っているボタンのアクションをどう付けるかの違いです。

EmbedActionCellの方は単純に、EmbedActionCellクラス内にボタンを押した時の定義も書かれています。


- (void)setIndexPath:(NSIndexPath *)indexPath {
    _indexPath = indexPath;
    [self.button addTarget:self action:@selector(pressButton:) forControlEvents:UIControlEventTouchUpInside];
}

- (void)pressButton:(id)pressButton {
    NSString *messageString = [NSString stringWithFormat:@"Button at section %d row %d was tapped.", self.indexPath.section, self.indexPath.row];
    UIAlertView *alert = [[UIAlertView alloc]
                                       initWithTitle:@"Button tapped!" message:messageString delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
}

Viewにボタンを押した時の動作についてまで書いてあるので、ちょっと扱いにくくなっています。

SmartCellの方はCocoaの日々: [iOS] UINib を使ったカスタム UITableViewCell の作り方(その3)ボタンの処理[改良版]の手法を使って、
コントローラ(SmartTableViewController)にボタンを押した時の動作を書くようにして、カスタムセルについては表示に関することだけになっています。

やり方としては、カスタムセルを生成する際にaddTarget:actionでイベントを設定しておいて、
UIEventからタッチした座標を取得して、その座標からどのセル(indexPath)なのかを取得できる(indexPathForControlEventメソッド部分)ので、
それぞれのセルに合わせたボタン動作等を定義できます。


- (UITableViewCell *)tableView:(UITableView *)tableView
                     cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *cellIdentifier = kCellIdentifier;
    SmartCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (!cell){
        cell = [[SmartCell alloc]
                           initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }

    // イベントを付ける
    [cell.button addTarget:self action:@selector(handleTouchButton:event:) forControlEvents:UIControlEventTouchUpInside];
    // Configure the cell...
    cell.accessoryType = UITableViewCellAccessoryNone;
    [self updateCell:cell atIndexPath:indexPath];

    return cell;
}

- (void)handleTouchButton:(UIButton *)sender event:(UIEvent *)event {
    NSIndexPath *indexPath = [self indexPathForControlEvent:event];
    NSString *messageString = [NSString stringWithFormat:@"Button at section %d row %d was tapped.", indexPath.section, indexPath.row];
    UIAlertView *alert = [[UIAlertView alloc]
                                       initWithTitle:@"Button tapped!" message:messageString delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
}

// UIControlEventからタッチ位置のindexPathを取得する
- (NSIndexPath *)indexPathForControlEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint p = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
    return indexPath;
}

大体の場合は、カスタムセルクラスに動作を書かないで、コントローラ側で動作を書いたほうが綺麗になると思います。
これでカスタムセルの作り方とセル内部に置いたボタンへのイベントリスナを付け方は終わりです。

TableViewについてはPro iOS Table Viewsという書籍が多分いちばん詳しく書かれていると思います。
(大体一通り載っています)

UITableViewは用意されたAPIを上手く活用すると、MVCがはっきりした構造になるので、
慣れるまでが分かりにくいですが、とても良くできていると思います。

Post Navigation