我在核心数据中设置了以下内容:一个具有许多成分的Dish实体,以及一个带有一个菜肴的Ingredient实体。
我无法获取我的多对数关系数据,即某个菜肴的成分。我尝试使用与每个菜相关的成分填充我的收集视图单元格。
我的核心数据模型设置如下:
我尝试了各种方法来获取数据。
我尝试过的一件事就是执行以下操作:Dish *dish = [self.fetchedResultsController objectAtIndexPath:indexPath];
然后再使用NSLog dish.ingredients(返回NSSet),但返回整个核心数据项,即createdAt日期,名称和所有内容,以及该菜肴的未经格式化的成分。
我尝试的另一件事是用Ingredient *ingredient = [dish.ingredients valueForKeyPath:@"ingredientName"];
创建一个新的Ingredient实体实例,但它返回一个未格式化的字符串(我希望它显示之前的UTF8编码,因为它包含特殊字符)。
Google搜索时的许多解决方案建议使用NSPredicate,但我无法弄清楚如何使用它。我对核心数据和XCODE一般都是新手,所以在这里任何帮助都会受到赞赏,即你在哪里实现NSPredicate,以及在我的情况下正确的谓词是什么?
一些支持代码:
我的collectionViewController:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSManagedObjectContext* context = [RKObjectManager sharedManager].managedObjectStore.mainQueueManagedObjectContext;
self.managedObjectContext = context;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Dish" 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:@"createdAt" ascending:NO];
NSArray *sortDescriptors = @[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
// 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 %@, %@", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
}
cellForItemAtIndexPath:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FOFPhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"photo" forIndexPath:indexPath];
self.object = [self.fetchedResultsController objectAtIndexPath:indexPath];
Dish *dish = [self.fetchedResultsController objectAtIndexPath:indexPath];
Ingredient *ingredient = ???;
cell.backgroundColor = [UIColor lightGrayColor];
[cell.imageView setImageWithURL:[NSURL URLWithString:[[NSString stringWithFormat:@"http://192.168.0.3:4000%@", dish.dishImage] description]] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
}];
cell.titleLabel.text = dish.dishName;
cell.headerLabel.text = dish.dishHeader;
cell.ingredientsLabel.text = [NSString stringWithFormat:@"%@", nil];
NSLog(@"%@", ingredient);
[self.collectionView reloadItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
return cell;
}
答案 0 :(得分:0)
简单的方法是您的第一种方法,然后只使用您关注的成分属性。核心数据更多地是关于对象编程而不是底层数据库,因此尝试模拟数据库查询通常不是正确的方法。
我还建议删除所有valueForKey
内容并使用实际的对象属性,以便代码更清晰,编译器可以帮助您更多地使用数据类型。
答案 1 :(得分:0)
如果您只为一个特定的Dish寻找配料,您必须设置您的fetchRequest for Ingredients(而不是Dish)并在Dish上设置谓词。要使以下代码有效,您可能需要首先创建NSManagedObject子类(借助Xcode Editor按钮)。
#import "Dish.h"
#import "Ingredient.h"
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Ingredient"];
[fetchRequest setFetchBatchSize:20];
//if dishname are unique values, set your predicate on it.
//You can also set your predicate on the dishID if dishName are not unique values (several dishes with a same name)
NSString *theDishIWant = @"Ratatouille"; //whatever Dish name you want
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"dish.dishName == %@", theDishIWant];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"ingredientname" ascending:YES];
[fetchRequest setSortDescriptors:@[sortDescriptor];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[RKObjectManager sharedManager].managedObjectStore.mainQueueManagedObjectContext sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
NSLog (@"%@", _fetchedResultsController);
return _fetchedResultsController;
}
您的configureCell: atIndexPath:
方法可能如下所示:
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
Ingredient *ingredient = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = ingredient.ingredientName;
cell.detailTextLabel.text = ingredient.ingredientValue;
}