インターフェイス ビルダーを使用してカスタム セルを作成しました。2 つのラベルと 1 つの UIButton があります。cellForRowAtIndexPath または willDisplayCell 内の各ラベルのテキストを問題なく設定できます。ただし、UIButton のイメージを設定すると、いずれかの場所で問題が発生します。問題は、私が完全には理解していないセルの再利用/キャッシュに関連していると思います。
主に willDisplayCell を使用する現在のコードを次に示しますが、ほとんどのコードを cellForRowAtIndexPath に移動しようとしても同じ結果になりました。
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
UIButton *check = (UIButton*) [cell.contentView viewWithTag:1];
UIButton *check2 = (UIButton*) [cell.selectedBackgroundView viewWithTag:1];
UILabel *from = (UILabel*) [cell.contentView viewWithTag:2];
UILabel *subject = (UILabel*) [cell.contentView viewWithTag:3];
// Configure the cell...
Message *rec = (Message*) Records[indexPath.row];
if(rec.Checked)
check.imageView.image = [UIImage imageNamed:@"Checkedbox.png"];
else
check.imageView.image = [UIImage imageNamed:@"Checkbox.png"];
check2.imageView.image = check.imageView.image;
from.text = rec.From;
subject.text = rec.Subject;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
return cell;
}
上記のコードでは、check2 は nil です。私はそれなしでも試しましたが、最近、修正の試みとしてそれを追加しました。
私は基本的にメッセージ リスト (受信トレイ) を作成しており、GMail のようなチェックボックスが必要です。私が持っているチェックボックスボタンのクリックイベントで:
- (IBAction)CheckClicked:(id)sender
{
UITableViewCell *cell = (UITableViewCell*) [[sender superview] superview];
NSIndexPath *indexPath = [[self tableView] indexPathForCell:cell];
Message *rec = (Message*) Records[indexPath.row];
rec.Checked = !rec.Checked;
[cell setNeedsLayout];
[cell.contentView setNeedsLayout];
[cell setNeedsDisplay];
[cell.contentView setNeedsDisplay];
[self.tableView reloadData];
}
上記の setNeedsLayout と setNeedsDisplay の呼び出しはすべて冗長であることを知っています。ほとんどの場合、機能しなかったことを示すためにそれらを使用しています。ほとんどの例では、セルの setNeedsLayout が機能するはずであると言われていますが、reloadData のみが少なくとも各セルを再描画/更新します。
クリックするとチェックボックスが正しく変更されますが、1 つのセルにチェックマークを付けてからクリックしてセルを強調表示すると、ビューが画面外にスクロールしてから戻るまでチェックボックスがオフになります。問題は、選択されたものと選択されていないものとで異なるビューがあることに関連していると思いましたが、それ以上に何を確認すればよいかわかりません。
編集:ほとんどのチュートリアルはこれに似たコードを使用しているため、ここでも試してみましたが、この使用法では、ブレークポイントを設定して cellForRowAtIndexPath が実行されていることを確認できても、セルがスクロールされて画面に戻るまで画像は変化しません。クリックイベントで reloadData が呼び出された後、各セルに対して再度呼び出され、チェックしたアイテムをチェックするように画像を正しく設定しています:
- (IBAction)CheckClicked:(id)sender
{
UITableViewCell *cell = (UITableViewCell*) [[sender superview] superview];
NSIndexPath *indexPath = [[self tableView] indexPathForCell:cell];
Message *rec = (Message*) Records[indexPath.row];
rec.Checked = !rec.Checked;
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
// NOTE: In my testing cell is never NULL, so I have no checking here.
UIButton *check = (UIButton*) [cell.contentView viewWithTag:1];
UILabel *from = (UILabel*) [cell.contentView viewWithTag:2];
UILabel *subject = (UILabel*) [cell.contentView viewWithTag:3];
// Configure the cell...
Message *rec = (Message*) Records[indexPath.row];
if(rec.Checked)
check.imageView.image = [UIImage imageNamed:@"Checkedbox.png"];
else
check.imageView.image = [UIImage imageNamed:@"Checkbox.png"];
from.text = rec.From;
subject.text = rec.Subject;
return cell;
}