我正在使用一个使用多个NSFetchedResultsControllers
(FRC)的应用程序,每个应用程序都用于我的数据模型中的不同Managed Object子类。其中几个FRC是UITableViewControllers
的一部分,但有几个不属于tableview
。我有两个问题:一,为什么我的一个FRC在我向MOC添加新对象时没有更新,另外两个,我应该为此目的使用FRC吗?我认为这将使我不必在整个代码中添加获取请求,但也许仅使用带有tableview
或其他此类对象的FRC才有意义。
所以,这里有详细信息。
与 @property (weak, nonatomic) NSFetchedResultsController *scheduleFetchedResultsController;
@property (weak, nonatomic) NSManagedObjectContext *managedObjectContext;
无关的其中一个FRC是一个跟踪时间表的FRC。 SetScheduleViewController具有以下属性(以及其他属性),它们通过父视图控制器传递:
- (NSFetchedResultsController *)scheduleFetchedResultsController {
if (_scheduleFetchedResultsController != nil) {
return _scheduleFetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Schedule" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"start" ascending:NO];
NSArray *sortDescriptors = @[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *fRC = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
NSError *error = nil;
if (![fRC performFetch:&error]) {
IFLErrorHandler *errorHandler;
[errorHandler reportErrorToUser:error];
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
self.scheduleFetchedResultsController = fRC;
return self.scheduleFetchedResultsController;
}
这个FRC是由另一个对象(它维护一个强大的指针)通过以下代码
创建的SetScheduleViewController
(旁白:cacheName设置为nil的原因是我似乎能够为这个应用程序中的许多FRC之一分配一个缓存名称,或者应用程序崩溃...如果只有一个FRC是给定一个缓存名称,其余的缓存名称设置为nil,一切似乎都很好,但我担心没有缓存,性能可能会很糟糕,因为持久存储的大小增长......但这是另一回事)
在SetScheduleViewController
中,可以创建或删除计划,并在加载 Schedule *newSchedule= [NSEntityDescription insertNewObjectForEntityForName:@"Schedule" inManagedObjectContext:self.managedObjectContext];
newSchedule.start=newStartTime;
//etc
NSError *saveError;
if (![self.managedObjectContext save:&saveError]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", saveError, [saveError userInfo]);
abort();
时加载最近创建的计划。创建计划时,将创建一个新的计划管理对象,然后按如下方式保存MOC:
SetScheduleViewController
这成功保存了新的MO,但FRC没有更新...我已经检查过这几种方式...例如,如果在保存新计划后我重新输入[[self.scheduleFetchedResultsController fetchedObjects]
并检查scheduleFetchedResultsController
计数]它不会增加。但是,如果我退出应用程序并再次打开它,请注意,FRC获取的对象计数会增加,新对象确实存在。
我应该注意tableviewcontrollers
没有分配代理,不像附加到tableviewcontrollers
的FRC,它们都运行正常。我没有分配一个委托,因为据我所知,tableview
中的FRC委托方法只处理FRC更改内容时更新tableview ...我没有看到任何刷新FRC的委托方法添加新对象并保存MOC时自身。
所以,我的两个问题又是:1)为什么FRC不刷新(我怎样才能刷新),2)使用FRC来管理未绑定的托管对象的获取结果是否有意义到{{1}},我应该只在每次需要访问对象列表时从MOC执行新的提取吗?
非常感谢任何帮助。
答案 0 :(得分:3)
在NSFetchedResultsController
文档中,声明如果没有设置委托,FRC处于“无跟踪”模式。此外,代理必须至少实施一种更改跟踪委托方法,以便启用更改跟踪。
委托不一定是表视图控制器,所以你可以使用你的
SetScheduleViewController
作为委托,只需实施controllerDidChangeContent:
委托方法。在那个方法里面,更新了
fetchedObjects
可用,您可以更新视图中的任何UI元素
控制器。
更新:从父VC传递FRC没有多大意义。 每个视图控制器都应该有自己的FRC 。所以scheduleFetchedResultsController
应该是childVC中的一个方法。由于FRC是在getter方法中“懒惰地”创建的,因此必须在某处调用getter。
在表视图控制器的情况下,这是因为所有表视图数据源方法
访问self.fetchedResultsController
。
如果您的childVC无法访问self.fetchedResultsController
,则访问FRC
不会被创建。这可能是为什么在[self.fetchedResultsController performFetch:&error]
中调用viewDidLoad
,如另一个答案所示,解决了您的问题。
如果结果,将调用委托方法controllerDidChangeContent:
在childVC的生命周期内设置更改 。这就是使用FRC的地方。
如果您只想在加载childVC时获取当前的对象集,那么
你不需要FRC,你可以只执行一个简单的提取,例如在viewDidLoad
。
答案 1 :(得分:1)
我之前遇到过同样的问题。原因是你没有执行FRC的获取。 在-viewDidLoad上添加以下代码:
NSError *error;
if (![self.fetchedResultsController performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}