核心数据和 NSSortDescriptor 未根据基于 NSString 的第三个描述符排序
Posted
技术标签:
【中文标题】核心数据和 NSSortDescriptor 未根据基于 NSString 的第三个描述符排序【英文标题】:Core Data and NSSortDescriptor not sorting according to third descriptor based on NSString 【发布时间】:2013-06-27 02:32:25 【问题描述】:我有一个 NSFetchRequest 正在获取一个名为“Player”的实体,我希望结果按以下顺序按 3 个属性排序:
-
名为“sendingoffOffence”的属性是否为 nil
“team.homeMatch”实体中的关系是否为零
我希望“数字”属性中的字符串按升序排序。
基本上,我希望所有有红牌的球员(“sendingOffence”不为零)出现在列表的顶部,然后根据球员是否在主队进行排序,然后最终将进攻组中的一组球员按球衣号码排序。
因此,我在获取请求中使用以下代码:
// Set the entity for the fetch request
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Player"
inManagedObjectContext:self.match.managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"match == %@", self.match];
[fetchRequest setPredicate:predicate];
// Sort the results
// Sort according to whether the user has a red card / sendingOffOffence
NSSortDescriptor *hasRedCard = [[NSSortDescriptor alloc] initWithKey:@"sendingoffOffence" ascending:NO];
// Sort according to whether the user is on the home team or not
NSSortDescriptor *isHomeTeam = [[NSSortDescriptor alloc] initWithKey:@"team.homeMatch" ascending:NO];
// Sort according to the player's jersey numbers
NSSortDescriptor *number = [[NSSortDescriptor alloc] initWithKey:@"number" ascending:YES selector:@selector(localizedStandardCompare:)];
[fetchRequest setSortDescriptors:@[hasRedCard, isHomeTeam, number]];
// Set the amount of records to retrieve from the database
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:self.match.managedObjectContext
sectionNameKeyPath:nil
cacheName:@"MatchCache"]
但是,当我执行上述代码时,我得到以下结果:
这个排序顺序是错误的,因为我希望以下顺序出现在红牌部分:
11 - 主页 12 - 主页 0 - 离开 11 - 离开 21 - 离开在黄牌区:
1 - 主页 2 - 主页 99 - 主页 1 - 离开 31 - 离开看起来黄牌部分排序正确,但红牌部分表现出非常奇怪的行为,使其看起来根本没有得到排序。
我很困惑为什么红牌部分无法正确排序 - 有什么想法吗?我应该只在内存中对这些对象进行排序,而不是依靠核心数据来获得我喜欢的顺序吗?
请注意,这是一个带有 SQL 支持的持久性存储的核心数据应用程序。
更新
以下是核心数据在我的 fetch 中使用的 SQL 语句:
CoreData: annotation: fetch using NSSQLiteStatement <0x11c77cd0> on entity 'SPlayer' with
sql text 'SELECT t0.Z_ENT, t0.Z_PK FROM ZFSMANAGEDOBJECT t0 LEFT OUTER JOIN ZSTEAM t1 ON
t0.ZTEAM = t1.Z_PK WHERE ( t0.ZMATCH1 = ? AND t0.Z_ENT = ?) ORDER BY
t0.ZSENDINGOFFOFFENCE DESC, t1.ZHOMEMATCH DESC, t0.ZNUMBER COLLATE NSCollateFinderlike '
【问题讨论】:
Turn on SQL debugging 并确保它正在生成您期望的 SQL。您可以调高调试级别,使其除了记录它发送的 SQL 之外,还记录它接收的数据。 您的托管对象上下文是否已保存?您确定您的标签不只是显示不正确吗? 我开启了SQL调试,添加了上面的SQL命令。我没有错误地显示项目,因为我的 FetchedResultsController 中的数组是未正确排序的东西。 你们是如何实现localizedCompare:
的?
@tilo 我正在使用作为 NSString 类一部分的本地化StandardCompare: 方法:developer.apple.com/library/mac/documentation/Cocoa/Reference/…
【参考方案1】:
这是未正确应用的行(对于 RED 卡盒):
NSSortDescriptor *isHomeTeam = [[NSSortDescriptor alloc] initWithKey:@"team.homeMatch" ascending:NO];
如果没有看到您的数据模型和一些示例数据,很难说为什么不能正确排序。我会假设这将首先放置 NIL 值,然后是适当的值(因此排序升序 NO 会做它在黄色卡片盒中所做的事情)。
如果我处于这种情况,我会检查我对排序顺序和这些 team.homeMatch 属性的假设。做一个测试,这是唯一的排序描述。
然后关注红/黄卡条件的不同之处。
【讨论】:
谢谢 Jess - 所以看起来当“sendingoffOffence”不为空时,其他排序描述符无法应用,但当它为空时它们可以正常工作。【参考方案2】:我们没有像这样检查它的 NSFetchedResultsController....
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Player"
inManagedObjectContext:self.match.managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"match == %@", self.match];
[fetchRequest setPredicate:predicate];
// Sort the results
// Sort according to whether the user has a red card / sendingOffOffence
NSSortDescriptor *hasRedCard = [[NSSortDescriptor alloc] initWithKey:@"sendingoffOffence" ascending:NO];
// Sort according to whether the user is on the home team or not
NSSortDescriptor *isHomeTeam = [[NSSortDescriptor alloc] initWithKey:@"team.homeMatch" ascending:NO];
[fetchRequest setSortDescriptors:@[hasRedCard, isHomeTeam]];
// Set the amount of records to retrieve from the database
[fetchRequest setFetchBatchSize:20];
NSArray *resultArray = [self.match.managedObjectContext executeFetchRequest:request error:&error];
NSSortDescriptor *number = [[NSSortDescriptor alloc] initWithKey:@"number" ascending:YES selector:@selector(localizedStandardCompare:)];
NSArray *sortedArray = [resultArray sortedArrayUsingDescriptors:[NSArray arrayWithObjects:number, nil]];
【讨论】:
以上是关于核心数据和 NSSortDescriptor 未根据基于 NSString 的第三个描述符排序的主要内容,如果未能解决你的问题,请参考以下文章
NSSortDescriptor 对核心数据获取请求没有影响
使用 NSSortDescriptor 按时间错误排序(带有核心数据)
核心数据 - 可以使用 NSSortDescriptor 中的块对 TableView 进行排序吗?