iOS:如何获取核心数据中数量最多的对象?

Posted

技术标签:

【中文标题】iOS:如何获取核心数据中数量最多的对象?【英文标题】:iOS : How to fetch objects with maximum count in core data? 【发布时间】:2015-02-25 11:05:56 【问题描述】:

我的核心数据模型中有两个类,它们是一对多的关系。

我们以班级专辑>班级歌曲为例进行说明。现在我想从Album 中获取(顶部)五个专辑,其中有Songs 的最大数量。

Class Album

    albumID (Integer)
    name    (String)
    songs   (class B)


Class Songs

    name   (String)
    length (Integer)


@class Songs;
@interface Album : NSManagedObject

@property (nonatomic, retain) NSNumber * albumID;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSSet *songs;

@end

@interface Album (CoreDataGeneratedAccessors)
- (void)addSongsObject:(Songs *)value;
- (void)removeSongsObject:(Songs *)value;
- (void)addSongs:(NSSet *)values;
- (void)removeSongs:(NSSet *)values;
@end

@class Album;

@interface Songs : NSManagedObject

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * length;
@property (nonatomic, retain) Album *owner;

@end

这就是我正在尝试的,

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Albums" inManagedObjectContext:[self context]]];
fetchRequest.fetchOffset = 0;
fetchRequest.fetchLimit = 5;
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"albumID" ascending:YES]];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"SELF @max.@count.songs"];
NSError *error = nil;
NSArray *albums = [[self context] executeFetchRequest:fetchRequest error:&error];

如果我不通过谓词,它可以正常工作。但问题在于谓词。它使应用程序崩溃并显示以下消息:

*** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“无法解析格式 字符串 "SELF @max.@count.songs"'

更新:我正在尝试与NSExpression 相同但无法同时执行max:count: 函数?以下是我尝试过的,

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Albums" inManagedObjectContext:[self context]]];

fetchRequest.fetchOffset = 0;
fetchRequest.fetchLimit = 5;

NSError *error = nil;

NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"songs"];
NSExpression *countExpression = [NSExpression expressionForFunction:@"count:" arguments:[NSArray arrayWithObject:keyPathExpression]];
//NSExpression *maxExpression = [NSExpression expressionForFunction:@"max:" arguments:[NSArray arrayWithObject:keyPathExpression]];

NSExpressionDescription *maxCountExpressionDescription = [[NSExpressionDescription alloc] init];
[maxCountExpressionDescription setName:@"squishes"];
[maxCountExpressionDescription setExpression:countExpression];

[fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:maxCountExpressionDescription]];
[fetchRequest setResultType:NSDictionaryResultType];

NSArray *albums = [[self context] executeFetchRequest:fetchRequest error:&error];

我想,我需要这样查询,

从专辑中选择专辑名称,最大值(计数(专辑.歌曲));

如何在NSFetchRequest中创建这样的查询,NSExpressionNSPredicate可以吗?

【问题讨论】:

Class Album...songs 属性中,它是一个什么样的类...?你能复制完整的头文件(以及生成的方法)吗? @geo,请查看更新后的问题。 【参考方案1】:

尝试删除:

fetchRequest.predicate = [NSPredicate predicateWithFormat:@"SELF @max.@count.songs"];

并将您的排序描述符替换为:

fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"songs.@count" ascending:NO]];

【讨论】:

我会按照你的方式进行,但现在这会导致另一个错误,*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Keypath containing KVC aggregate where there shouldn't be one; failed to handle songs.@count' 知道现在出了什么问题吗? 看起来这个请求对于 Core Data 来说太复杂了。试试这个:***.com/questions/19160032/… 谢谢,但我也检查过了。我会尽快更新我的问题。我想要 n 中的前 5 名。歌曲数量最多的专辑。所以我想我需要执行一些混合查询或表达式?如何将NSExpressionmax:count: 函数组合在一起?【参考方案2】:

我以不同的方式解决了这个问题,我在 Album 类中添加了一个 songsCount 属性。每次从专辑中添加/删除歌曲时,我都会增加/减少它。然后我按降序获取所有按songsCount 排序的专辑。

一旦我可以获取所有专辑,我将运行一个 for 循环并取出前五个对象。

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Albums" inManagedObjectContext:[self context]]];
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"songsCount" ascending:NO]];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"songsCount > 0"];
NSError *error = nil;
NSArray *albums = [[self context] executeFetchRequest:fetchRequest error:&error];
NSMutableArray *top5Albums = [NSMutableArray array];
NSInteger totalCounts = [albums count];
NSInteger maxIndex = (totalCounts >= 5) ? 5 : totalCounts;
for(NSInteger index = 0; index < maxIndex; index++) 
    [top5Albums addObject:[albums objectAtIndex:index]];

【讨论】:

以上是关于iOS:如何获取核心数据中数量最多的对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 mongoose 从 mongoDB 中获取一定数量的对象? (Node.js)

如何从核心数据中获取最多计数的字符串值

如何获取核心数据中多个子模型的最小值

SwiftUI - 如何限制 ForEach 中显示的对象数量

如何使用组合来分配从核心数据获取请求返回的元素数量?

获取核心数据对象的子对象的属性?