OStack程序员社区-中国程序员成长平台

标题: ios - 刷新未绑定(bind)到 uitableview 的 nsfetchedresultscontroller [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-13 05:43
标题: ios - 刷新未绑定(bind)到 uitableview 的 nsfetchedresultscontroller

我正在编写一个使用许多 NSFetchedResultsControllers (FRC) 的应用程序,每个应用程序用于我的数据模型中的不同托管对象子类。其中几个 FRC 是 UITableViewControllers 的一部分,但有几个不是。我有两个问题:第一,当我向 MOC 添加新对象时,为什么我的一个 FRC 没有更新,第二,我是否应该为此目的使用 FRC?我认为它可以让我不必在整个代码中放置获取请求,但也许只有将 FRC 与 tableview 或其他此类对象一起使用才有意义。

所以,这里是详细信息。

不绑定(bind)到 tableview 的 FRC 之一是跟踪时间表的 FRC。 SetScheduleViewController 具有以下属性(以及其他属性),这些属性是通过父 View Controller 传入的:

  @property (weak, nonatomic) NSFetchedResultsController *scheduleFetchedResultsController;
  @property (weak, nonatomic) NSManagedObjectContext *managedObjectContext;

这个 FRC 是由另一个对象(它维护一个指向它的强指针)通过以下代码创建的

- (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;
}

(顺便说一句:cacheName 设置为 nil 的原因是我似乎只能将缓存名称分配给此应用程序中的众多 FRC 中的一个,或者应用程序崩溃......如果只有一个 FRC给定一个缓存名称,其余的缓存名称设置为 nil,一切似乎都很好,尽管我担心没有缓存,随着持久存储大小的增长,性能可能会很糟糕......但这是另一回事)

SetScheduleViewController 中,可以创建或删除一个计划,并在加载SetScheduleViewController 时加载最近创建的计划。创建计划时,会创建一个新的计划管理对象,然后将 MOC 保存如下:

 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();

这成功保存了新的 MO,但 FRC 没有更新...我已经检查了几种方法...例如,如果在保存新计划后我重新输入 SetScheduleViewController 并检查 [[self.scheduleFetchedResultsController fetchedObjects] count] 它没有增加。但是,如果我退出应用程序并再次打开它,你瞧,FRC 获取的对象计数会增加,并且新对象确实存在。

我应该注意到 scheduleFetchedResultsController 没有分配委托(delegate),这与 FRC 附加到 tableviewcontrollers 不同,它们都可以正常工作。我没有分配委托(delegate),因为据我所知,tableviewcontrollers 中的 FRC 委托(delegate)方法仅在 FRC 更改内容时处理更新 tableview...我没有看到任何委托(delegate)方法添加新对象并保存 MOC 时刷新 FRC 本身。

所以,我的两个问题又是:1) 为什么 FRC 不刷新(以及我如何让它刷新),2) 使用 FRC 来管理未绑定(bind)的托管对象的获取结果是否有意义到 tableview,我是否应该在每次需要访问对象列表时简单地从 MOC 执行新的提取?

非常感谢任何帮助。



Best Answer-推荐答案


NSFetchedResultsController 文档中指出,如果没有设置委托(delegate),FRC 处于“无跟踪”模式。此外,委托(delegate)必须至少实现一种变更跟踪委托(delegate)方法才能启用变更跟踪。

委托(delegate)不必是表格 View Controller ,因此您可以使用您的 SetScheduleViewController 作为委托(delegate),只需实现 controllerDidChangeContent: 委托(delegate)方法。在该方法中,更新的 fetchedObjects 是可用的,你可以例如更新 View 中的任何 UI 元素 Controller 。

更新:从 parentVC 传递 FRC 没有多大意义。 每个 View Controller 都应该有自己的 FRC。所以 scheduleFetchedResultsController 应该是 childVC 中的一个方法。由于 FRC 是在 getter 方法中“延迟”创建的,因此必须在某个地方调用 getter。

在 TableView Controller 的情况下,发生这种情况是因为所有 TableView 数据源方法 访问 self.fetchedResultsController

如果您的 childVC 不访问 self.fetchedResultsController 那么 FRC 不会被创建。这可能是在 viewDidLoad 中调用 [self.fetchedResultsController performFetch:&error] 的原因,正如另一个答案中所建议的那样,解决了您的问题。

委托(delegate)方法 controllerDidChangeContent: 如果结果会被调用 在 childVC 的生命周期内设置更改。这就是使用 FRC 的意义所在。

如果您只想在加载 childVC 时获取当前对象集,那么 你不需要 FRC,你可以执行一个简单的 fetch,例如在 viewDidLoad.

关于ios - 刷新未绑定(bind)到 uitableview 的 nsfetchedresultscontroller,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20604490/






欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) Powered by Discuz! X3.4