保存核心数据相关数据并使用具有多个实体的 NSPredicate 和 NSFetchedResultsController 检索

Posted

技术标签:

【中文标题】保存核心数据相关数据并使用具有多个实体的 NSPredicate 和 NSFetchedResultsController 检索【英文标题】:Saving Core Data related data and retrieving with NSPredicate and NSFetchedResultsController with multiple entities 【发布时间】:2014-10-15 19:45:10 【问题描述】:

我对 Core Data 还很陌生,并且仍在尝试了解访问和过滤相关数据。我的问题是要么我没有将数据正确地放入 managedObjectContext,要么我没有正确地将其拉出。 (我认为是第一个,但我不确定。)

这是我的数据模型,其中包含两个一对多相关的实体:(我计划在一级关系正常工作后进行重构。)

我有一个 SeasonsVC,您可以在其中单击赛季名称,该赛季的比赛列表应该会出现在 GamesVC 中,并且您可以选择添加或编辑现有比赛。这在第一次通过时效果很好。我可以通过 GameDetailsVC 中的这段代码添加和编辑游戏:

 -(IBAction)done:(UIBarButtonItem *)sender 

    Game *game = nil;

    if (self.gameToEdit != nil) 
        game = self.gameToEdit;
        NSLog(@"Hitting gametoedit");
     else 
        game = [NSEntityDescription insertNewObjectForEntityForName:@"Game" inManagedObjectContext:self.managedObjectContext];
        NSLog(@"Hitting new game");
    

    game.opponent = self.opponentTextField.text;
    //season.seasonDescription = self.seasonDescriptionTextView.text;

    NSLog(@"Game to edit: %@", game.opponent);
    //NSLog(@"Season: %@", season);

    //NSLog(@"MOC in done: %@", self.managedObjectContext);
    //NSLog(@"Season name: %@", season.seasonName);

    [self dismissViewControllerAnimated:YES completion:nil];

然后我可以通过 fetchedResultsController 和委托方法在 GamesVC 中查看比赛,但每场比赛都与每个赛季相关联。一旦我尝试使用谓词过滤数据,以便我只看到为该赛季添加的游戏,所有游戏都消失了。以下是 GamesVC 的代码:

- (NSFetchedResultsController *)fetchedResultsController 

    if (_fetchedResultsController != nil) 
        return _fetchedResultsController;
    

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription
                                   entityForName:@"Game" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    NSLog(@"Season name for predicate %@", self.season.seasonName);//shows correct season name

    NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"season.seasonName like '%@'", self.season.seasonName]];

    [fetchRequest setPredicate: predicate];


    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"dateOfGame" ascending:NO] ;

    [fetchRequest setSortDescriptors:@[sortDescriptor]];

    [fetchRequest setFetchBatchSize:20];

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

    return _fetchedResultsController;


由于我可以在谓词语句之前记录正确的赛季名称,我认为当我将添加的游戏放入 MOC 中的 done: 方法时,它们并没有与正确的赛季“关联”;否则,我希望谓词能够找到它们。

你能帮助这个菜鸟吗?谢谢。

【问题讨论】:

【参考方案1】:

一天后我把这个整理好了。我需要对我正在做的事情进行三处更改。

首先,在我的 GameListVC 中的 prepareForSegue 中,我需要通过将代码更改为此将季节传递给 GameDetailsVC。 (只加了一行:controller.season = self.season)

    //pass the Season object to be edited
    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
    Game *gameToEdit = [self.fetchedResultsController objectAtIndexPath:indexPath];
    controller.gameToEdit = gameToEdit;
    controller.season = self.season;

其次,我必须将这两行添加到 GameDetailsVC 中的 done: 方法中,从而将新的/编辑的游戏对象放入 MOC。

NSMutableSet *games = [self.season mutableSetValueForKey:@"games"];
[games addObject:game];

第三,我需要在 GameListVC 的 fetchedResultsController 方法中简化谓词语句。

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"season.seasonName like %@", self.season.seasonName];

所以,回答我自己的问题,我既没有保存与赛季相关的游戏,而且我的谓词是错误的。

我希望这对其他新手有所帮助。

【讨论】:

以上是关于保存核心数据相关数据并使用具有多个实体的 NSPredicate 和 NSFetchedResultsController 检索的主要内容,如果未能解决你的问题,请参考以下文章

核心数据不保存一个实体的属性

核心数据保存和加载到多个实体

具有核心数据的多个持久性存储

核心数据需要时间来插入具有获取实体的记录并设置为关系

相关实体的 iOS 核心数据持久性

如何将来自多个视图控制器的数据保存到单个核心数据实体中