使用“!=”谓词时,NSFetchedResultsController会创建额外的空行

时间:2011-03-25 21:36:07

标签: iphone ios nsfetchedresultscontroller

我有一个UITableViewController,它由NSFetchedResultsController填充。我的CoreData实体有一个名为" submitter_id"的属性。根据我的控制器的初始化方式,我想获取与给定的submitter_id匹配的记录,或者哪个DON&t; T匹配所述的submitter_id。 "匹配"案件工作正常,但我遇到的问题是"没有匹配"案件。我的sqlite数据库是正确的,但我在TableView中得到了额外的空行。

在下面的输出中,我从Core Data获得了正确的3条记录,但是NSFetchedResultsController(或某人)在我的TableView中添加了34个空行。注意:空行数遵循一个模式,这可能是一个线索:如果我删除应用程序并从头开始,我首先得到17个空行+3个好行。当我第二次运行时,我得到34个空行+3个好行。从那时起,它稳定在34个空行。有趣的是,我的测试数据集中有17条记录。

2011-03-25 15:35:17.256 test[54095:207] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZDELETED, t0.ZDESCRIPTION, t0.ZITEMID, t0.ZICON, t0.ZAVG, t0.ZNAME, t0.ZCREATIONDATE, t0.ZIMAGE, t0.ZSUBMITTERID, t0.ZUSER FROM ZITEM t0 WHERE  t0.ZSUBMITTERID <> ? ORDER BY t0.ZNAME DESC
2011-03-25 15:35:17.257 test[54095:207] CoreData: details: SQLite bind[0] = 32
2011-03-25 15:35:17.258 test[54095:207] CoreData: annotation: sql connection fetch time: 0.0017s
2011-03-25 15:35:17.258 test[54095:207] CoreData: annotation: fetch using <NSSQLiteStatement: 0x5f920f0> returned 3 rows with values: (
    "Plastic ballpoint",
    "Walmart readers",
    Blue
)
2011-03-25 15:35:17.263 test[54095:207] CoreData: annotation: total fetch execution time: 0.0071s for 3 rows.
2011-03-25 15:35:17.264 test[54095:207] numberOfSectionsInTableView: 1
2011-03-25 15:35:17.264 test[54095:207] numberOfRowsInSection 0: 37
2011-03-25 15:35:17.265 test[54095:207] indexPath 0
2011-03-25 15:35:17.268 test[54095:207] name: pen
2011-03-25 15:35:17.268 test[54095:207] indexPath 1
2011-03-25 15:35:17.269 test[54095:207] name: glasses
2011-03-25 15:35:17.269 test[54095:207] indexPath 2
2011-03-25 15:35:17.270 test[54095:207] name: checkbook
2011-03-25 15:35:17.270 test[54095:207] indexPath 3
2011-03-25 15:35:17.272 test[54095:207] name: (null)
2011-03-25 15:35:17.273 test[54095:207] indexPath 4
2011-03-25 15:35:17.275 test[54095:207] name: (null)
2011-03-25 15:35:17.275 test[54095:207] indexPath 5
2011-03-25 15:35:17.275 test[54095:207] name: (null)
2011-03-25 15:35:17.278 test[54095:207] indexPath 6
2011-03-25 15:35:17.279 test[54095:207] name: (null)
2011-03-25 15:35:17.279 test[54095:207] indexPath 7
2011-03-25 15:35:17.280 test[54095:207] name: (null)
2011-03-25 15:35:17.281 test[54095:207] indexPath 8
2011-03-25 15:35:17.281 test[54095:207] name: (null)

这是我设置NSFetchedResultsController的代码:

   - (BOOL) setupFRC
    {
        NSFetchRequest *request = [[NSFetchRequest alloc] init];
        request.entity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:self.managedObjectContext];
        request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:NO]];

        NSPredicate *p1;
        if (self.listType == MY_ITEMS_LIST) {
            p1 = [NSPredicate predicateWithFormat:@"submitterID == %qu", appDelegate.user.userID];
        }
        else {
            p1 = [NSPredicate predicateWithFormat:@"submitterID != %qu", appDelegate.user.userID];
        }
        request.predicate = p1;

        NSFetchedResultsController *frc = [[NSFetchedResultsController alloc]
                                           initWithFetchRequest:request
                                           managedObjectContext:self.managedObjectContext
                                           sectionNameKeyPath:nil
                                           cacheName:nil];
        frc.delegate = self;

        self.fetchedResultsController = frc;
        [frc release];
        [request release];

        return YES;
    }

    - (void)performFetchForTableView
    {
        NSError *error = nil;
        [self.fetchedResultsController performFetch:&error];
        if (error) {
            NSLog(@"[CoreDataTableViewController performFetchForTableView:] %@ (%@)", [error localizedDescription], [error localizedFailureReason]);
        }
        [self.tableView reloadData];
    }

我在这里格式化单元格:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForManagedObject:(NSManagedObject *)managedObject
{
    static NSString *CellIdentifier;
    if (self.listType == MY_ITEMS_LIST) {
        CellIdentifier = @"RSMyItemCell";
    }
    else {
        CellIdentifier = @"RSTBDItemCell";
    }

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }

    // Configure the cell...
    CDItem *item = (CDItem *)managedObject;
    cell.textLabel.text = item.name;
    cell.detailTextLabel.text = item.description;
    NSLog(@"name: %@",item.name);
    return cell;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    NSInteger n = [sectionInfo numberOfObjects];
    NSLog(@"numberOfRowsInSection %d: %d",section,n);
    return n;
}

我确定我错过了一些东西,但我对如何进一步调试感到困惑。有人见过这个吗?如果您想查看其他任何代码段,请与我们联系。

谢谢!

STU

1 个答案:

答案 0 :(得分:0)

有时候只需要清晰的头脑即可。周末回来后,我看到了问题所在。供您参考,以下是发生的事情:

在应用启动时,我使用从服务器下载的项目列表更新CoreData DB。在尝试添加之前,我检查CoreData中是否已存在给定项目。错误是我打电话

[NSEntityDescription insertNewObjectForEntityForName:inManagedObjectContext:]

在执行我的存在检查之前。这导致创建的实体没有相应的托管对象。即使CoreData将正确的数据集返回给NSFetchedResultsController,控制器也必须使用实体计数来确定[sectionInfo numberOfObjects];

在任何情况下,在“不存在”子句(发生insertNewObjectForEntityForName)内移动addObject调用可以解决问题。

谢谢,

STU