2

I am playing around with an app that keeps track of when people receive a publication. I have two core data entities, publication and person, which have to-many relationships to each other as each can have many of the other. Publication <<->> Person.

I am trying to iterate through the relationships so that if a person has received the publication the cell should be style check mark. If they haven't then it should be cell style plain. Here is what I have so far:

-(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;
        }
    }
}

When I run this it will display all persons as long as none have a relationship to this publication. But once I select their name I get this log:

Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'

Here is the didSelectRow method:

- (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];

    }

}

I'm sure I'm going about this all wrong, any help would be greatly appreciated.

Figured it out. Here is what I used

-(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(模型-视图-控制器)编程范式的所有规则。

您显示复选标记的基本方法是可以的。参考数据模型来决定使用哪个 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 回答