- ベストアンサー
iPhoneアプリ開発でチェックマークが付けられない問題について
- iPhoneアプリ開発において、tableviewcellにチェックマークを付けるコードを実装しているが、意図しないセルにもチェックマークが表示される問題が発生している。また、スクロールするとチェックマークが外れる現象も発生している。
- さまざまなサイトで調査した結果、上記のコードが最もよく見かけるコードであることが分かった。
- チェックマーク以外の要素は正常に表示されているため、問題はチェックマークの追加処理にある可能性が高い。心当たりのある方はアドバイスをお願いします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
No.1の回答を、サンプルコードの形にすると、こうなります。 #define CELL @"Cell" #import "TableViewController.h" @interface TableViewController () @end @implementation TableViewController { NSMutableArray *dataArray; } - (void)viewDidLoad { [super viewDidLoad]; NSMutableDictionary *item; dataArray = [NSMutableArray arrayWithCapacity: 12]; item = [@{@"month": @"January", @"accessory": @(UITableViewCellAccessoryNone)} mutableCopy]; [dataArray addObject: item]; item = [@{@"month": @"Febtruary", @"accessory": @(UITableViewCellAccessoryNone)} mutableCopy]; [dataArray addObject: item]; item = [@{@"month": @"March", @"accessory": @(UITableViewCellAccessoryNone)} mutableCopy]; [dataArray addObject: item]; item = [@{@"month": @"April", @"accessory": @(UITableViewCellAccessoryNone)} mutableCopy]; [dataArray addObject: item]; item = [@{@"month": @"May", @"accessory": @(UITableViewCellAccessoryNone)} mutableCopy]; [dataArray addObject: item]; item = [@{@"month": @"June", @"accessory": @(UITableViewCellAccessoryNone)} mutableCopy]; [dataArray addObject: item]; item = [@{@"month": @"July", @"accessory": @(UITableViewCellAccessoryNone)} mutableCopy]; [dataArray addObject: item]; item = [@{@"month": @"August", @"accessory": @(UITableViewCellAccessoryNone)} mutableCopy]; [dataArray addObject: item]; item = [@{@"month": @"September", @"accessory": @(UITableViewCellAccessoryNone)} mutableCopy]; [dataArray addObject: item]; item = [@{@"month": @"October", @"accessory": @(UITableViewCellAccessoryNone)} mutableCopy]; [dataArray addObject: item]; item = [@{@"month": @"November", @"accessory": @(UITableViewCellAccessoryNone)} mutableCopy]; [dataArray addObject: item]; item = [@{@"month": @"December", @"accessory": @(UITableViewCellAccessoryNone)} mutableCopy]; [dataArray addObject: item]; } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return dataArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CELL forIndexPath:indexPath]; cell.textLabel.text = dataArray[indexPath.row][@"month"]; cell.accessoryType = (UITableViewCellAccessoryType)[dataArray[indexPath.row][@"accessory"] intValue]; return cell; } - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView cellForRowAtIndexPath: indexPath]; if (cell.accessoryType == UITableViewCellAccessoryNone) { cell.accessoryType = UITableViewCellAccessoryCheckmark; dataArray[indexPath.row][@"accessory"] = @(UITableViewCellAccessoryCheckmark); } else { cell.accessoryType = UITableViewCellAccessoryNone; dataArray[indexPath.row][@"accessory"] = @(UITableViewCellAccessoryNone); } } @end
その他の回答 (2)
- harawo
- ベストアンサー率58% (3742/6450)
回答No.2のサンプルコードの、いちぶ修正です。 - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView cellForRowAtIndexPath: indexPath]; // if (cell.accessoryType == UITableViewCellAccessoryNone) { // この行を変更 if ([dataArray[indexPath.row][@"accessory"] intValue] == UITableViewCellAccessoryNone) { cell.accessoryType = UITableViewCellAccessoryCheckmark; dataArray[indexPath.row][@"accessory"] = @(UITableViewCellAccessoryCheckmark); } else { cell.accessoryType = UITableViewCellAccessoryNone; dataArray[indexPath.row][@"accessory"] = @(UITableViewCellAccessoryNone); } } 「MVCデザインパターンを準拠しよう」といっている手前、ビュー(テーブルセル)に依存したプログラムでは、統一性がありませんからね。
- harawo
- ベストアンサー率58% (3742/6450)
まず、MVCデザインパターンについて説明します。これはウィキペディアで、「Model View Controller」という項目で記載がありますから、あわせて読んでください。 ひとことでいうと、プログラムの構成は、データ(Model)と表示(View)を別々にしましょう、という考え方の指針です。インターフェイスを変更したら、データ構造も作り直さないといけないという設計では、むだなコストがかかりすぎるという理由で、このような考え方が生まれました。ここでMVCデザインパターンの詳細を語るつもりはないので、これ以上は説明しませんが、iOSのUIKitは、このMVCデザインパターンに準拠した構成になっています。UIKitのクラスに「Controller」と付く名前が多数ありますが、MVCデザインパターンを準拠している証です。Controllerは、データを参照しながら、ビューを制御する役割を担います。 UIControlのサブクラス、スライダーや、スイッチ、そしてUILabelなどは、そのインスタンスにデータを保持することができます。スライダーはvalueというプロパティ、スイッチならonというプロパティ、ラベルならtextというプロパティ、それぞれがデータを保持するプロパティです。なので、これらのオブジェクトを使えば、MVCデザインパターンに準拠しないプログラムを作ることは可能です。しかしながらテーブルとテーブルセルは、それ自身にデータを保持することができません。加えて、テーブルセルはテーブルの行数分の数存在するわけではないので、その理由だけでもテーブルセルにデータを保持することは不可能です。 テーブルセルのアクセサリの状態も、テーブル、テーブルセルから独立した、なんらかのデータに保存します。一般的には、NSArrayインスタンスを使うことになるでしょう。テキストラベルのテキスト、アクセサリの状態……と、項目ごとに配列を作っていたら、管理がうっとうしくなるので、複数の項目を保持したNSDictionaryインスタンスを、NSArrayに格納するという方向が、現実的でしょう。
お礼
非常に丁重な解説とサンプルコードで分かりやすかったです。 おかげで問題解決いたしました、ありがとうございます。