通过iOS Core Data关系迭代

时间:2012-04-09 16:02:54

标签: core-data ios5

我正在玩一款能够跟踪人们何时收到出版物的应用程序。 我有两个核心数据实体,即publication和person,它们彼此之间有很多关系,因为每个实体可以拥有许多其他关系。 出版物<< - >>人

我正在尝试迭代关系,以便如果某人收到了该出版物,则该单元格应为样式复选标记。如果他们没有那么它应该是细胞风格平原。以下是我到目前为止的情况:

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

1 个答案:

答案 0 :(得分:1)

您的代码存在一个基本的设计缺陷。您正在使用UI元素(复选标记)来通知您的数据模型。这非常容易出错并且违反了MVC(模型 - 视图 - 控制器)编程范例的所有规则。

关于显示复选标记的基本方法是可以的。咨询数据模型以决定使用哪个UI元素。但是,它不是使用索引遍历对象的最佳方法。此外,滚动tableview时循环非常昂贵。这是另一种方法:

(我假设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];