NSFetchRequest 用于行中的子对象

Posted

技术标签:

【中文标题】NSFetchRequest 用于行中的子对象【英文标题】:NSFetchRequest for sub objects in rows 【发布时间】:2014-04-27 04:46:40 【问题描述】:

我的数据模型如下: 类别

—>名字

—>items(“汽车”类型的项目数组)

我正在尝试使用部分作为名称来获取,并且行应该是项目(这是一个 NSArray)

这是我的代码,我希望将行作为 Car 返回,但它仍然返回“Category”。那么,什么是 NSFetchRequest?

NSFetchRequest *request=[[NSFetchRequest alloc] initWithEntityName:@"Categories"];


NSSortDescriptor *sortDesc=[[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDesc]];

fetchController=[[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:delegate.managedContext sectionNameKeyPath:@"name" cacheName:nil];
NSError *fetchError;
[fetchController performFetch:&fetchError];

我已附上模型的图片。

取车代码如下。

AppDelegate *del=(AppDelegate*)[UIApplication sharedApplication].delegate;
NSFetchRequest *request=[[NSFetchRequest alloc] initWithEntityName:@"Car"];


NSSortDescriptor *sortDesc=[[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDesc]];

fetchController=[[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:del.managedContext sectionNameKeyPath:@"Categories.name" cacheName:nil];
NSError *fetchError;
[fetchController performFetch:&fetchError];

代码在这里上传https://www.dropbox.com/s/jjk0nve3pmytui2/TestAppData%202.zip

注意:- 我正在考虑显示空白部分,因为我可以查看具有“添加”按钮的标题。所以,通过这个用户可以很容易地知道类别的数量。

为了实现上面“注意”中提到的事情,我尝试了以下方法。我创建了一个CarViewController2。它创建了相同数量的类别,但行数取决于categoriesRelationship(这是一个NSOrderedSet)。可以通过取消注释 ViewController.m 的 (IBAction) addCategory:(id) sender 中的一些代码来测试这一点。 (取消评论一次,之后再评论)代码已经更新,可以下载了。

如果需要,请更正代码。谢谢。

【问题讨论】:

【参考方案1】:

您的设置应该是:

NSFetchRequest *request=[[NSFetchRequest alloc] initWithEntityName:@"Car"];
NSSortDescriptor *sortDesc=[[NSSortDescriptor alloc] initWithKey:@"category.name" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDesc]];

fetchController=[[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                    managedObjectContext:delegate.managedContext 
                                                      sectionNameKeyPath:@"category.name" 
                                                               cacheName:nil];

category.name 假设 Category items 的反向关系是 Car category(一对多关系)

请注意,您可能希望将排序描述符更改为按某些 Car 属性排序

编辑:

发布模型和当前代码后,您不能按 Category 名称对数据进行分段,因为这是多对多关系。 不同部分不能有重复项。

如果Car 'c' 属于类别 'g1' 和 'g2' 你要么需要自己构建数据结构,要么引入一个连接汽车和类别的中间实体,这将是请求将立足。

编辑 2:

在您的项目中,您将carRelation 设置为Categories 实体,这将允许您形成以下请求:

NSFetchRequest *request=[[NSFetchRequest alloc] initWithEntityName:@"Car"];
NSSortDescriptor *sortDesc=[[NSSortDescriptor alloc] initWithKey:@"carName" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDesc]];

fetchController=[[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                    managedObjectContext:delegate.managedContext 
                                                      sectionNameKeyPath:@"carRelation.categoryName" 
                                                               cacheName:nil];

这仍然不会显示其中没有汽车的类别(因为它应该有汽车视图和类别视图)。

编辑 3:

您对CarViewController.m的代码更正:

-(void) getData
    AppDelegate *del=(AppDelegate*)[UIApplication sharedApplication].delegate;
    NSFetchRequest *req=[[NSFetchRequest alloc] initWithEntityName:@"Car"];
    NSSortDescriptor *descriptor1=[[NSSortDescriptor alloc] initWithKey:@"carRelationship.categoryName" ascending:YES];
    NSSortDescriptor *descriptor2=[[NSSortDescriptor alloc] initWithKey:@"carName" ascending:YES];
    [req setSortDescriptors:@[descriptor1,descriptor2]];
    fetchController=[[NSFetchedResultsController alloc] initWithFetchRequest:req managedObjectContext:del.managedContext sectionNameKeyPath:@"carRelationship.categoryName" cacheName:nil];
    NSError *fetchError;
    fetchController.delegate=self;
    [fetchController performFetch:&fetchError];
    NSLog(@"Fetch ERROR= %@",fetchError);


- (NSString*) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section

    id<NSFetchedResultsSectionInfo> sectionInfo=[[fetchController sections] objectAtIndex:section];
    return [sectionInfo name];

正如我之前解释的,这仍然不会显示其中没有汽车的类别

【讨论】:

我确实添加了关系,但它没有更新核心数据模型类,所以我必须删除并重新创建该类。如果“汽车”实体为空,它会显示一个部分列表。由于实体“类别”中仍然存在类别(例如 SUV 和跑车等)。可以举个例子吗? @andyPaul 这不会导致空白部分(其中没有汽车的类别)。重新生成具有关系的类(尽管将其添加到实体中就足够了),并在添加 Car 对象时设置它。你想要什么类型的例子? 我已经编辑了代码,如果我需要指定其他内容来解决它,请告诉我。 @andyPaul 您应该按carName 属性排序,这是在您的Car 实体中定义的属性。 抓取时崩溃。【参考方案2】:

我们试试

NSFetchRequest *request=[[NSFetchRequest alloc] initWithEntityName:@"Category"];
NSSortDescriptor *sortDesc=[[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDesc]];
fetchController=[[NSFetchedResultsController alloc] initWithFetchRequest:request   managedObjectContext:delegate.managedContext sectionNameKeyPath:@"name" cacheName:nil];
NSError *fetchError;
[fetchController performFetch:&fetchError];

NSArray *categories = [fetchedResultsController fetchedObjects];
for(Category *c in categories)
   NSSet *items = c.items;// array that you want

【讨论】:

performFetch 填充数组,节数和行数由 fetchController 设置。您提供的解决方案不适用于我现有的代码。 @andyPaul:performFetch 返回 BOOL 而不是数组。 NSArray *categories = [fetchedResultsController fetchedObjects] -> 你得到什么类别?什么数组?

以上是关于NSFetchRequest 用于行中的子对象的主要内容,如果未能解决你的问题,请参考以下文章

NSFetchRequest 在第一次运行时返回对象,但以后不返回

NSFetchRequest 带有用于递归 CoreData 实体关系的排序描述符

使用javascript替换textarea中所有行中的子字符串

用于 groupby 和 count 组合的 NSFetchRequest

NSFetchRequest 没有看到 NSManagedObjectContext 中关系的变化

NSFetchRequest 不适用于谓词