核心数据一对多关系

Posted

技术标签:

【中文标题】核心数据一对多关系【英文标题】:Core Data One-to-Many Relationship 【发布时间】:2012-03-14 02:14:28 【问题描述】:

我的核心数据模型中有一对多的关系。一餐可以有多种食物。我想用一顿饭的食物填满一张桌子。因此,如果第一餐有苹果、橙子和柠檬,那么餐桌将由这三种食物组成。

非常感谢任何帮助,因为我完全陷入困境。

这是我的模型:

还有 NSManagedObject 类:

Meal.h

@class Food;

@interface Meal : NSManagedObject

@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSSet *foods;

@end

@interface Meal (CoreDataGeneratedAccessors)

- (void)addFoodsObject:(Food *)value;
- (void)removeFoodsObject:(Food *)value;
- (void)addFoods:(NSSet *)values;
- (void)removeFoods:(NSSet *)values;

@end

食物.h

@class Meal;

@interface Food : NSManagedObject

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) Meal *meals;

@end

这是我尝试尝试的代码,但我遇到了一些问题。

- (NSFetchedResultsController *)fetchedResultsController 
    
    if (_fetchedResultsController != nil)
        return _fetchedResultsController;

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Food" inManagedObjectContext:_context];
    [fetchRequest setEntity:entity];

    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"Meal.foods == %@", entity]];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
    [fetchRequest setFetchBatchSize:20];

    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:nil cacheName:@"Root"];

    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;

    [fetchRequest release];
    [theFetchedResultsController release];

    return _fetchedResultsController;      

【问题讨论】:

你坚持什么?请准确告诉我们您的问题是什么。 为什么在这里使用一对多的关系?如果Food 代表一种种类的食物而不是特定的食物,那么我希望给定的Food 实例能够与不止一顿饭相关。 【参考方案1】:

您提到您遇到了问题,但没有提到问题是什么;但是您的 NSFetchRequest 谓词对我来说看起来不正确。同样,Food 上定义的 meals 是复数,但关系是一对一的——有点混乱。

您的 UITableView 应该使用来自单个 MealFoods 填充,对吧?我们称它为Meal_thisMeal,那么获取谓词应该是:

NSPredicate *foodPredicate = [NSPredicate predicateWithFormat:@"meals == %@",_thisMeal];
[fetchRequest setPredicate:foodPredicate];

所以,您要获取的实体是Food;这个谓词确保他们的meals 属性是你的UITableViewController 正在寻找的Meal

更新以显示如何获取命名的Meal

获取名为“Custom Meal”的Meal

Meal *_thisMeal = nil;
// this assumes that there should be only one Meal named "Custom Meal"
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Meal"];
NSPredicate *fetchPredicate = [NSPredicate predicateWithFormat:@"name = %@",@"Custom Meal"];

NSError *fetchError = nil;
NSArray *meals = [_context executeFetchRequest:request error:&fetchError];
if( fetchError )
    NSLog(@"%s - ERROR while fetching Meal: %@,%@",__FUNCTION__,fetchError,[fetchError userInfo]);
else if( [meals count] != 0 )
    _thisMeal = [meals objectAtIndex:0];

【讨论】:

你能解释一下这顿饭_thisMeal吗?这条线会给我错误 Meal *_thisMeal。那条线应该是什么? 抱歉,我的意思是您的UITableViewController 必须“知道”正在显示的餐食,您的NSFetchRequest 才能正常工作。据推测,它可能从上游某处获得 Meal 引用,可能是在之前的表视图中被选中之后。为了便于讨论,我只是将其称为 _thisMeal,因为我不知道在您的代码中,对特定 Meal 的引用是什么。 你能告诉我如何获得膳食_thisMeal吗?假设我想要一顿名为“Custom Meal”的餐点,然后我想显示 Custom Foods 中的食物。这整个概念让我感到困惑。【参考方案2】:

您的膳食和食物分类有误。最好杀死那些并让 XCode 自动重新生成 这些类通过(确保您的实体被选中):

在您的fetchedResultsController getter 方法中,删除该行:

[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"Meal.foods == %@", entity]];

您通常会使用谓词来过滤数据,例如包含香蕉的食物。您当前的谓词目前没有真正意义。它的意思是“给我饭菜,里面有一种叫做‘实体’的食物,……没有意义。

既然你想吃饭……

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Food" inManagedObjectContext:_context]; 

应该是:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Meal" inManagedObjectContext:_context];

(注意@"Meal")。

然后,您可以通过meal.foods 访问每餐的食物。

此行:self.fetchedResultsController = theFetchedResultsController; 应该是:_fetchedResultsController = theFetchedResultsController; 你所做的基本上就是调用你当前所在的方法。

【讨论】:

以上是关于核心数据一对多关系的主要内容,如果未能解决你的问题,请参考以下文章

核心数据以一对多关系排序

如何在一对多核心数据关系中获取特定数据?

核心数据以一对多关系保存在后台

iOS核心数据一对多关系NSSET

核心数据一对多插入与现有关系swift

核心数据:NSPredicate 一对多对多关系