繁体   English   中英

核心数据对多关系获取

[英]Core Data to-many relationship fetching

我在核心数据中进行了以下设置:一个包含很多配料的Dish实体,以及一个包含一个盘子的Ingredient实体。

我在获取一对多关系数据(即某道菜的配料)时遇到麻烦。 我正在尝试使用与每个菜肴相关的成分填充收藏视图单元格。

我的核心数据模型设置如下:

核心数据模型

我尝试了各种方法来获取数据。

我尝试过的一件事是执行以下操作: Dish *dish = [self.fetchedResultsController objectAtIndexPath:indexPath]; 然后是NSLog dish.ingredients(返回NSSet),但是返回整个核心数据项,即createdAt日期,名称和所有内容,以及该菜式的未格式化版本。

我尝试做的另一件事是使用Ingredient *ingredient = [dish.ingredients valueForKeyPath:@"ingredientName"];创建一个Ingredient实体的新实例Ingredient *ingredient = [dish.ingredients valueForKeyPath:@"ingredientName"]; ,但是返回一个未格式化的字符串(我希望它在显示之前先经过UTF8编码,因为它包含特殊字符)。

谷歌搜索时有很多解决方案建议使用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;
}

简单的方法是您的第一种方法,然后仅使用成分中关心的属性。 核心数据更多地是关于对象编程而不是底层数据库,因此尝试模拟数据库查询通常不是正确的方法。

我还建议您删除所有valueForKey内容并使用实际的对象属性,以使代码更加清晰,并且编译器可以帮助您更多地使用数据类型。

如果您只为一个特定的菜品寻找配料,则必须为配料(而不是菜品)设置fetchRequest,并在菜品上设置谓词。 为了使以下代码正常工作,您可能需要首先创建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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM