持久存储更改后如何刷新 fetchedResultsController
Posted
技术标签:
【中文标题】持久存储更改后如何刷新 fetchedResultsController【英文标题】:how to refresh fetchedResultsController after persistent store change 【发布时间】:2014-10-21 04:13:36 【问题描述】:在编程方面我是一个周末战士,所以我可能做错了什么......
我有一个拆分视图控制器、核心数据、nsfetchedResultsController,一切都很好。我现在可以选择让用户创建persistentStore.sqlite 文件的备份文件。当用户从备份文件恢复时,tableview 不会反映任何更改。最重要的是,从那时起,无法从 tableview 添加/删除进行任何持久的更改。当我退出应用程序并重新启动它时,所有数据都在备份中,并且一切正常。
如何强制 tableview 从 fetched results 控制器获取现在的新信息?或者我如何强制
以下是我迄今为止尝试过的一些零散的尝试:
MasterViewController.m
- (void)viewDidLoad
context = [[OSCDStackManager sharedManager] managedObjectContext];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadFetchedResults) name:OSFilesUpdatedNotification object:nil];
- (void)reloadFetchedResults:(NSNotification*)note
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error])
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
if (note)
[self.tableView reloadData];
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
NSError *error = nil;
[self.fetchedResultsController performFetch:&error];
[self.tableView endUpdates];
[self.tableView reloadData];
来自 tableview 上的手动刷新下拉...
-(void) updateTable
context = [[OSCDStackManager sharedManager] managedObjectContext];
NSError *error = nil;
[self.fetchedResultsController performFetch:&error];
//[self.tableView endUpdates];
[self.tableView reloadData];
[self.refreshControl endRefreshing];
- (void)viewWillAppear:(BOOL)animated
[self.tableView reloadData];
- (NSFetchedResultsController *)fetchedResultsController
context = [[OSCDStackManager sharedManager] managedObjectContext];
if (_fetchedResultsController != nil)
return _fetchedResultsController;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSArray *sortDescriptors = @[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
//[NSFetchedResultsController deleteCacheWithName:@"cache"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error])
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
return _fetchedResultsController;
即使这是我邻居的应用程序,我也不想告诉他在备份后杀死并重新启动应用程序...
解决方案最终成为以下两个答案的组合,
- (void)reloadFetchedResults
self.fetchedResultsController = nil;
[NSFetchedResultsController deleteCacheWithName:@"cache"];
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error])
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
[self.tableView reloadData];
【问题讨论】:
【参考方案1】:你删除缓存了吗?
您需要先将缓存名称设置为fetchedResultsController
(注意末尾的cacheName
参数):
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:query
managedObjectContext:context
sectionNameKeyPath:nil
cacheName:@"CACHE_NAME"];
然后在进行更新时删除缓存:
[NSFetchedResultsController deleteCacheWithName:@"CACHE_NAME"];
执行此操作后,通过执行此操作再次从核心数据加载:
NSError *error;
if (![self.fetchedResultsController performFetch:&error])
// Update to handle the error appropriately.
NSLog(@"Unresolved error loading data %@, %@", error, [error userInfo]);
exit(-1); // Fail
[self.tableView reloadData];
【讨论】:
【参考方案2】:消除你的 FRC
-(void)reloadData
NSError *error = nil;
self.fetchedResultsController = nil;
if (![self.fetchedResultsController performFetch:&error])
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
else
[self.tableView reloadData];
** 编辑 ** 如果前面的“自我”不明显,你需要在课堂上的某个地方
-(NSFetchedResultsController *)fetchedResultsController
if (!_fetchedResultsController)
_fetchedResultsController = [NSFetchedResultsController alloc]initWithFetchRequest:aFetchRequest
managedObjectContext:aManagedObjectContext // the main thread MOC
sectionNameKeyPath:nil cacheName:nil];
// addional FRC setup etc.
return _fetchedResultsController;
【讨论】:
这个终于解决了,但我还需要删除缓存。 您必须将nil
出您的NSFetchedResultsController
吗?我从来没有这样做过。我只需要删除缓存。
这个例子也是错误的,你设置self.fetchedResultsController = nil
但是你在下一行使用它。
@Evils 我认为说这是错误的不公平......问题是'如何在持久存储更改后刷新 fetchedResultsController' 清除缓存也可以。但你可以拥有sectionNameKeyPath:nil cacheName:nil]'
惰性对象相当普遍......它应该是 Obj C 和 Swift 的第二天性
这是一个了不起的提示!我不知道你必须取消它。没有“无效”电话或类似电话。谢谢,@Magoo!【参考方案3】:
如果您要替换 sqlite 文件,您可能最好将所有内容都拆掉并从新的托管对象上下文开始。这是与删除商店类似的问题。
【讨论】:
以上是关于持久存储更改后如何刷新 fetchedResultsController的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 试图从 FetchedResults 获取对象但没有找到方法