核心数据 NSFetchRequest 按类别排序方法返回值

Posted

技术标签:

【中文标题】核心数据 NSFetchRequest 按类别排序方法返回值【英文标题】:Core Data NSFetchRequest Sort by Category Method Return Value 【发布时间】:2014-02-15 03:57:38 【问题描述】:

如何按我正在获取的实体类别中的方法返回的值对获取的结果进行排序?

在我的类别中,我将实体的一对多关系中的几个值相加,然后除以关系中的对象数,有效地创建了一个平均值,我在我的类别方法中作为浮点值返回。

这是我的代码:

在 Category.h 中

- (float)smallPenaltyAvg;

在 Category.m 中

- (float)smallPenaltyAvg
    float smallPenaltyAvg = 0;
    for (Match *mtch in self.matches) 
        smallPenaltyAvg += [mtch.penaltySmall floatValue];
    

    if ([self.matches count] > 0) 
        smallPenaltyAvg = (float)smallPenaltyAvg/(float)[self.matches count];
    

    return smallPenaltyAvg;

当我在我创建的 Core Data Table View Controller 类中调用它时......

NSFetchRequest *poolRequest = [[NSFetchRequest alloc] initWithEntityName:@"Team"];
poolRequest.predicate = [NSPredicate predicateWithFormat:@"regionalIn.name = %@", _regionalToDisplay];
poolRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"smallPenaltyAvg" ascending:YES]];

我在Category.h 文件本身之外的每个文件中导入了Category.h 文件。

它给了我以下错误:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath smallPenaltyAvg not found in entity <NSSQLEntity Team id=5>

我不能这样做吗?

如果我是,我做错了什么?

【问题讨论】:

【参考方案1】:

我认为这与持久存储的类型无关。

诀窍是在托管对象模型中创建一个适当的属性,并将其标记为Transient。然后覆盖此属性的 getter 以进行计算。

现在您的 fetch 请求应该可以按预期工作(尽管 fetched results 控制器有一些注意事项)。

至于SQLite问题,当你用

添加SQLite存储时
 - (NSPersistentStore *)addPersistentStoreWithType:(NSString *)storeType 
    configuration:(NSString *)configuration 
    URL:(NSURL *)storeURL 
    options:(NSDictionary *)options 
    error:(NSError **)error

只需将NSSQLiteStoreType 传递为storeType。其他选项是二进制和内存中的,所以从这个意义上说,这确实是“默认”。

【讨论】:

您是否介意为返回浮点值(或带有浮点值的 NSNumber)的瞬态属性做一个示例平均计算,以便我可以看到语法? 使用关键路径更有效地完成平均计算。 NSNumber *average = [fetchedObjects valueForKeyPath:@"@avg.amount"];. 不,我说的是从 Team 到 Match 的“对多”关系中 Match 对象的平均属性值。 IE。 Match 对象有一个名为“penaltySmall”的属性,它是一个 NSNumber。我想检索团队“对多”关系中的所有匹配对象,并返回所述团队中匹配的平均“penaltySmall”浮点值【参考方案2】:

这在使用支持 SQLite 存储时是不可能的。

我的建议是您保留平均属性,并通过覆盖 Match setCategory: 属性并在此处为添加的每个匹配项进行计算来自己维护它。

【讨论】:

那么默认的Core Data存储是SQLite? 不这么认为。在将其添加到协调器时,您必须指定您创建的商店的类型。 我的猜测是后备存储是SQLite(猜测FSA ...基于NSManagedDocument),您可以检查您的文件系统并自己查看... 我得到的错误说我使用的是 NSSQL,而不是 SQLite。我也不认为我在代码中添加了任何指定 SQLite 的内容 由于您的错误,很明显您确实使用了支持 SQLite 存储(至少是您使用的框架)。【参考方案3】:

我为解决我的问题所做的就是从 Team 对象的所有 Match 对象的属性中为我需要的每个平均值或总和创建一个新属性,然后在 TeamCategory 文件中创建一个填充这些平均值的方法,并且每次将 Match 对象插入 Team 对象时都会调用该方法。花了一段时间才完成,但现在可以了。如果有更好的解决方案,我仍然愿意提供建议。

【讨论】:

以上是关于核心数据 NSFetchRequest 按类别排序方法返回值的主要内容,如果未能解决你的问题,请参考以下文章

如何在一个 NSFetchRequest 中获取核心数据关系?

默认情况下,核心数据获取(NSFetchRequest)是不是以任何特定方式排序?

按计算结果排序 NSFetchRequest

核心数据按两个Descriptor对数据进行排序

核心数据和 NSSortDescriptor 未根据基于 NSString 的第三个描述符排序

iOS Core Data NSFetchRequest groupby 关系对象