NSFetchedResultsController始终不返回任何行

时间:2011-12-04 06:38:10

标签: ios core-data

我正在尝试使用NSFetchedResultsController处理我的tableview,但尽管我尽最大努力正确设置它,但它始终没有返回任何行。我通过Finder打开了我的数据存储,并通过SQLite编辑器验证了实际上有很多记录,但它总是返回零。我错过了什么?

控制器的自定义getter:

- (NSFetchedResultsController *)fetchedResultsController {
    if (fetchedResultsController_ != nil) {
        return fetchedResultsController_;
    }

    RBGameItemController* itemController = [RBGameItemController sharedInstance];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"GameItem" inManagedObjectContext:itemController.managedObjectContext];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

    [fetchRequest setFetchBatchSize:20];

    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest  
                                                                                                  managedObjectContext:itemController.managedObjectContext 
                                                                                                    sectionNameKeyPath:nil 
                                                                                                             cacheName:@"Root"];
    self.fetchedResultsController = theFetchedResultsController;
    self.fetchedResultsController.delegate = self;

    [sort release];
    [fetchRequest release];
    [theFetchedResultsController release];

    return self.fetchedResultsController;
}

我正在viewDidLoad中获取数据:

- (void)viewDidLoad {
    [super viewDidLoad];

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }
}

获取结果委托:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    // The fetch controller is about to start sending change notifications, so prepare the table view for updates.
    [self.tableView beginUpdates];

    NSLog(@"controllerWillChangeContent");
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
    NSLog(@"controller:didChangeObject:");
    UITableView *tableView = self.tableView;

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            // Reloading the section inserts a new row and ensures that titles are updated appropriately.
            [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
    NSLog(@"controller:didChangeSection:");
    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    NSLog(@"controllerDidChangeContent:");
    // The fetch controller has sent all current change notifications, so tell the table view to process all updates.
    [self.tableView endUpdates];
}

我正在实现section和row number的两种方法,它们为section返回1,为行返回0:

- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
    int sections = [[self.fetchedResultsController sections] count];
    NSLog(@"sections=%i", sections);
     return sections;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    int rows = [sectionInfo numberOfObjects];

    NSLog(@"rows=%i", rows);

    return rows;
}

3 个答案:

答案 0 :(得分:11)

您是否尝试过使用获取请求手动执行查询以确保它返回您所期望的内容?在您的自定义fetchedResultsController尝试执行:

NSArray *entities = [itemController.managedObjectContext executeFetchRequest:fetchRequest error:&error];
NSLog(@"%d",entities.count);

看看会发生什么。

另外,尝试在没有缓存的情况下设置fetchedRequestController。您可能是在应用程序的其他部分按名称重用相同的缓存?

答案 1 :(得分:5)

对代表的分配:

 self.fetchedResultsController.delegate = self;

最后一行:

return self.fetchedResultsController;

这将导致对此方法的循环调用。不要写这样的代码。

此调用中的关键点是managedObjectContext,sortDescriptor和实体。因此,请确保这些都不是零,并且值是您所期望的。

static NSString *const NSString *kMyFetchedResultsControllerCacheName = @"RootCache";



- (NSFetchedResultsController *)fetchedResultsController {
    if (_fetchedResultsController == nil) {
        [NSFetchedResultsController deleteCacheWithName:];
        RBGameItemController* itemController = [RBGameItemController sharedInstance];

        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription entityForName:NSStringFromClass([GameItem class]) inManagedObjectContext:itemController.managedObjectContext];
        [fetchRequest setEntity:entity];

        NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO];
        [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

        [fetchRequest setFetchBatchSize:20];

        NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:itemController.managedObjectContext sectionNameKeyPath:nil cacheName:kMyFetchedResultsControllerCacheName];
        self.fetchedResultsController = fetchedResultsController;
        fetchedResultsController.delegate = self;
    }

    return _fetchedResultsController;
}

最后,您始终需要确保调用performFetch,可能在viewDidLoad

NSError *error = nil;
[self.fetchedResultsController performFetch:&error];
if (error != nil) {
    NSLog(@"%@", error.localizedDescription);
}

答案 2 :(得分:0)

为cacheName传递nil解决了我的问题...不确定原因。