Ios NSSortDescriptor按最后一个消息时间戳对会话进行排序

Ios NSSortDescriptor按最后一个消息时间戳对会话进行排序,ios,swift,uitableview,core-data,nssortdescriptor,Ios,Swift,Uitableview,Core Data,Nssortdescriptor,我是新来的NSSortDescriptor,任何提示都非常感谢 我有一个包含对话的UITableView。每个对话可以包含多条消息。消息将显示在另一个视图中。这基本上就像是iMessage。 在对话表视图中,我想按最新消息对对话进行排序 为简单起见,我绘制了以下抽象模型: 每个对话都有一组消息。每个消息都有一个日期 当我获取对话时(使用NSFetchedResultsController),我希望它们按照属性消息的日期进行排序。 我认为这一定很简单,只使用计算属性,但这不起作用 我尝试使用密钥

我是新来的
NSSortDescriptor
,任何提示都非常感谢

我有一个包含对话的
UITableView
。每个对话可以包含多条消息。消息将显示在另一个视图中。这基本上就像是iMessage。 在对话表视图中,我想按最新消息对对话进行排序

为简单起见,我绘制了以下抽象模型:

每个
对话
都有一组
消息
。每个
消息
都有一个
日期

当我获取
对话时(使用
NSFetchedResultsController
),我希望它们按照属性
消息的
日期进行排序。
我认为这一定很简单,只使用计算属性,但这不起作用

我尝试使用密钥路径:

request.sortDescriptors = [NSSortDescriptor(key: "messages.date", ascending: false)]
。。。但这与
***由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“此处不允许使用多个密钥”

编辑:关于可能的重复。

当我尝试将此应用于
NSSet
的所有元素时,我得到以下错误:
***由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因是:“实体中未找到keypath ALL messages.date”

使用以下排序描述符:

request.sortDescriptors = [NSSortDescriptor(key: "ALL messages.date", ascending: false)]

在NSDate上创建一个类别,返回当前日历和时区从一天开始的时间间隔,然后使用该时间间隔进行排序

@interface NSDate (CBVAdditions)


- (NSTimeInterval)cbvTimeIntervalSinceStartOfDay;


@end

@implementation NSDate (CBVAdditions)


- (NSTimeInterval)cbvTimeIntervalSinceStartOfDay
{

    NSCalendar *calendar = [NSCalendar currentCalendar];

    NSTimeZone *timeZone = [NSTimeZone defaultTimeZone];


    NSDateComponents *dateComponents = [calendar components:(NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:self];


    [dateComponents setCalendar:calendar];

    [dateComponents setTimeZone:timeZone];

    NSInteger hoursComponent = dateComponents.hour * 3600;

    NSInteger minutesComponent = dateComponents.minute * 60;

    double secondsComponent = dateComponents.second;

    NSTimeInterval toReturn = hoursComponent + minutesComponent + secondsComponent;

    return toReturn;

}
然后,您可以将NSSortDescriptor与以下键一起使用
@“dateProperty.cbvTimeIntervalsEntertOfDay”
执行实际排序。 例如,我展示了事件类和一些完成排序的代码

@interface Event : NSObject

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSDate *eventDate;

@end

@implementation Event

- (NSString *)description
{
    NSString *desc = [NSString stringWithFormat:@"%@, name = %@, eventDate = %@",[super description], self.name, [self.eventDate descriptionWithLocale:[NSLocale currentLocale]]];
    return desc;
}
@end

Event *e1 = [Event new];

e1.eventDate = [NSDate date];

e1.name = @"e1";

Event *e2 = [Event new];

e2.eventDate = [NSDate dateWithTimeIntervalSinceNow:(-1 * 22 * 3600)];

e2.name = @"e2";

Event *e3 = [Event new];

e3.eventDate = [NSDate dateWithTimeIntervalSinceNow:3600];

e3.name = @"e3";

NSArray *events = @[e1,e2,e3];

NSLog(@"Events = %@", events);

NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"eventDate.cbvTimeIntervalSinceStartOfDay" ascending:YES];

NSArray *sortedEvents = [events sortedArrayUsingDescriptors:@[sortDescriptor]];

NSLog(@"Sorted Events = %@", sortedEvents);
代码显示了以下输出:

2013-01-15 15:50:54.221 DateSortingFun[67319:c07] Events = (
    "<Event: 0x717b050>, name = e1, eventDate = Tuesday, January 15, 2013, 3:50:54 PM Mountain Standard Time",
    "<Event: 0x717b620>, name = e2, eventDate = Monday, January 14, 2013, 5:50:54 PM Mountain Standard Time",
    "<Event: 0x717b650>, name = e3, eventDate = Tuesday, January 15, 2013, 4:50:54 PM Mountain Standard Time" ) 


2013-01-15 15:50:54.222 DateSortingFun[67319:c07] Sorted Events = (
    "<Event: 0x717b050>, name = e1, eventDate = Tuesday, January 15, 2013, 3:50:54 PM Mountain Standard Time",
    "<Event: 0x717b650>, name = e3, eventDate = Tuesday, January 15, 2013, 4:50:54 PM Mountain Standard Time",
    "<Event: 0x717b620>, name = e2, eventDate = Monday, January 14, 2013, 5:50:54 PM Mountain Standard Time" )
2013-01-15 15:50:54.221日期排序乐趣[67319:c07]活动=(
“,name=e1,eventDate=2013年1月15日星期二下午3:50:54山地标准时间”,
“,name=e2,eventDate=2013年1月14日星期一,下午5:50:54山地标准时间”,
“,name=e3,eventDate=2013年1月15日星期二下午4:50:54山地标准时间”)
2013-01-15 15:50:54.222日期排序乐趣[67319:c07]已排序事件=(
“,name=e1,eventDate=2013年1月15日星期二下午3:50:54山地标准时间”,
“,name=e3,eventDate=2013年1月15日星期二下午4:50:54山地标准时间”,
“,name=e2,eventDate=2013年1月14日星期一下午5:50:54山地标准时间”)

您要做的是在对话中添加一个最后消息日期属性。这将允许您有效地对对话进行排序

这就是所谓的非规范化。您需要确保此最后消息日期字段是最新的。有很多方法。一种方法是覆盖对话中的
willSave()
,并检查消息关系或任何消息是否有更改--检查时,需要确保不会触发任何对象错误。如果有任何更改,则更新对话的最后消息日期属性


本书性能一章中的如何建立有效的数据模型一节进行了更详细的介绍

可能是我发现的那个的复制品。但这是针对
NSPredicate
而不是
nssortddescription
。这只在你想过滤东西的时候起作用,不幸的是不适合排序。它仍然适用
messages
是一个
NSSet
,因此它没有要排序的
date
属性。我尝试了它,但没有可以比较的属性?我用我试过的代码更新了原始问题。您能解释一下如何将其用于
NSSortDescriptor
?谢谢,但您缺少对话和消息之间的1:n关系(实际上包含日期)。问题在于,我无法访问会话消息数组中的date属性。
2013-01-15 15:50:54.221 DateSortingFun[67319:c07] Events = (
    "<Event: 0x717b050>, name = e1, eventDate = Tuesday, January 15, 2013, 3:50:54 PM Mountain Standard Time",
    "<Event: 0x717b620>, name = e2, eventDate = Monday, January 14, 2013, 5:50:54 PM Mountain Standard Time",
    "<Event: 0x717b650>, name = e3, eventDate = Tuesday, January 15, 2013, 4:50:54 PM Mountain Standard Time" ) 


2013-01-15 15:50:54.222 DateSortingFun[67319:c07] Sorted Events = (
    "<Event: 0x717b050>, name = e1, eventDate = Tuesday, January 15, 2013, 3:50:54 PM Mountain Standard Time",
    "<Event: 0x717b650>, name = e3, eventDate = Tuesday, January 15, 2013, 4:50:54 PM Mountain Standard Time",
    "<Event: 0x717b620>, name = e2, eventDate = Monday, January 14, 2013, 5:50:54 PM Mountain Standard Time" )