NSFetchedResultsController 在 PerformFetch 上崩溃:使用缓存时

作者:编程家 分类: objective 时间:2025-06-18

使用缓存时,NSFetchedResultsController 在 PerformFetch 上崩溃是一种常见的问题。NSFetchedResultsController 是 Core Data 框架中的一个类,用于管理和监控与数据库对应的结果集。当我们在使用 NSFetchedResultsController 的 performFetch 方法时,如果开启了缓存功能,就有可能会遇到崩溃的情况。

崩溃的原因通常是由于缓存数据与实际数据不一致所导致的。当我们首次执行 performFetch 方法时,NSFetchedResultsController 会将结果集的数据缓存在内存中,以提高后续的查询性能。然而,如果在缓存数据的情况下,数据库中的数据发生了变化(例如增加、修改或删除数据),那么缓存数据就会与实际数据不一致,从而导致崩溃。

为了解决这个问题,我们需要在合适的时机手动更新 NSFetchedResultsController 的缓存数据。通常,在数据发生变化时,我们可以监听 Core Data 的 NSManagedObjectContextDidSaveNotification 通知,并在回调方法中执行缓存数据的更新操作。下面是一个示例代码:

objective-c

- (void)setupFetchedResultsController {

NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Person"];

fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];

fetchRequest.fetchBatchSize = 20;

NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"PersonCache"];

fetchedResultsController.delegate = self;

NSError *error = nil;

if (![fetchedResultsController performFetch:&error]) {

NSLog(@"Fetch error: %@", error);

}

self.fetchedResultsController = fetchedResultsController;

// 监听数据变化的通知

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(managedObjectContextDidSaveNotification:) name:NSManagedObjectContextDidSaveNotification object:nil];

}

- (void)managedObjectContextDidSaveNotification:(NSNotification *)notification {

[self.managedObjectContext performBlock:^{

[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];

NSError *error = nil;

if (![self.fetchedResultsController performFetch:&error]) {

NSLog(@"Fetch error: %@", error);

}

dispatch_async(dispatch_get_main_queue(), ^{

[self.tableView reloadData];

});

}];

}

解决 NSFetchedResultsController 缓存崩溃问题

以上代码是一个基本的 NSFetchedResultsController 配置示例。在 setupFetchedResultsController 方法中,我们创建了一个 fetchRequest 对象,并指定了排序方式、批量大小等属性。然后,我们将 fetchRequest 对象与 managedObjectContext 关联,并指定了缓存名称为 "PersonCache",以开启缓存功能。

在 managedObjectContextDidSaveNotification 方法中,我们首先执行 mergeChangesFromContextDidSaveNotification 方法,将保存通知中的变化合并到当前的 managedObjectContext 中。然后,我们再次执行 performFetch 方法,以更新 NSFetchedResultsController 的缓存数据。最后,我们在主队列中刷新 UI,以显示最新的数据。

通过以上的代码,我们可以解决 NSFetchedResultsController 在 PerformFetch 上崩溃的问题。通过手动更新缓存数据,我们保证了缓存与实际数据的一致性,从而避免了崩溃的发生。