2

人々がいつ出版物を受け取ったかを追跡するアプリをいじっています。私は 2 つのコア データ エンティティ、出版物と人物を持っています。これらは互いに対多の関係を持ち、それぞれが他の多くの関係を持つことができます。出版物 <<->> 人物。

人が出版物を受け取った場合、セルがスタイルチェックマークになるように、関係を反復しようとしています。そうでない場合は、セル スタイル プレーンにする必要があります。これが私がこれまでに持っているものです:

-(void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {

    Person *personForCell = (Person *) [fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", personForCell.firstName, personForCell.lastName];


    NSArray *issuesForPersonArray = [personForCell.issues allObjects];

    if ([issuesForPersonArray count] != 0) {

    for (int i = 0; i <= [issuesForPersonArray count]; i++) {
        if ([issuesForPersonArray objectAtIndex:i] == km) {
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
        }else {
            cell.accessoryType = UITableViewCellAccessoryNone;
        }
    }
}

これを実行すると、この出版物と関係がない限り、すべての人が表示されます。しかし、名前を選択すると、次のログが表示されます。

キャッチされていない例外 'NSRangeException' が原因でアプリを終了しています。理由: ' * -[__NSArrayI objectAtIndex:]: 境界を超えたインデックス 1 [0 .. 0]'

didSelectRow メソッドは次のとおりです。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:NO];
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if (cell.accessoryType == UITableViewCellAccessoryNone) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        // Reflect selection in data model
        Person *personSelected = (Person *) [fetchedResultsController objectAtIndexPath:indexPath];
        [publication addPersonObject:personSelected];


    } else if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
        cell.accessoryType = UITableViewCellAccessoryNone;
        // Reflect deselection in data model
        Person *personSelected = (Person *) [fetchedResultsController objectAtIndexPath:indexPath];
        [publication removePersonObject:personSelected];

    }

}

私はこれについてすべて間違っていると確信しています。どんな助けでも大歓迎です。

理解した。これが私が使ったものです

-(void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {

    Person *personForCell = (Publisher *) [fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", personForCell.firstName, personForCell.lastName];

    NSMutableArray *issuesForPersonArray = [[personForCell.publication allObjects] mutableCopy];

    if ([issuesForPersonArray count] != 0) {

        for (Publication *publicationForPerson in issuesForPersonArray) {
            if (publicationForPerson == publication) {
                cell.accessoryType = UITableViewCellAccessoryCheckmark;
            }else {
                cell.accessoryType = UITableViewCellAccessoryNone;
            }
        }
    }
}
4

1 に答える 1

1

コードに根本的な設計上の欠陥があります。UI 要素 (チェック マーク) を使用してデータ モデルを通知します。これは非常にエラーが発生しやすく、MVC (Model-View-Controller) プログラミング パラダイムのすべてのルールに違反します。

チェックマークの表示に関する基本的なアプローチは問題ありません。データ モデルは、使用する UI 要素を決定するために参照されます。ただし、インデックスを使用してオブジェクトをループするのは最善の方法ではありません。また、テーブルビューをスクロールするときのループは非常に高価です。別のアプローチを次に示します。

(km問題の出版エンティティのインスタンスへの参照だと思います。)

NSPredicate *predicate = [NSPredicate predicateWithFormat:
   @"ANY issues == %@", km];
NSArray *filteredArray = [[personForCell allObjects] 
   filteredArrayUsingPredicate:predicate];
if (filteredArray.count > 0) // check
else // uncheck

厳密に言えば、まだ反復がありますが、フレームワークがそれを行っているため、これらの範囲外エラーに対処する必要はありません。

関係を変更する場合は、同様の方法を使用してこの情報を取得する必要があります。

if (filteredArray.count > 0) [personSelected removeIssuesObject:km];
else [personSelected addIssuesObject:km];
[self.tableView reloadData];
于 2012-04-09T17:23:14.777 に答える