刷新一个与uitableview无关的nsfetchedresultscontroller

时间:2013-12-16 06:07:24

标签: ios nsfetchedresultscontroller

我正在使用一个使用多个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执行新的提取吗?

非常感谢任何帮助。

2 个答案:

答案 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]);
}