2016-01-03 1 views
1

Я новичок в NSSortDescriptor поэтому любые советы приветствуются.NSSortDescriptor sort Беседы от последнего сообщения timestamp

У меня есть UITableView, который содержит разговоры. В каждом разговоре может быть несколько сообщений. Сообщения отображаются в другом представлении. Это в основном как iMessage. В разговоре-TableView я хочу заказать разговоры по самым последним сообщениям.

Для простоты я нарисовал следующую абстрактную модель: enter image description here

Каждый conversation имеет набор messages. Каждый message имеет date.

Когда я Извлечение conversation (используя NSFetchedResultsController) Я хочу, чтобы по приказу date имущества messages. Я думал, что это довольно легко, просто используя вычисляемые свойства, но это не работает.

Я попытался с помощью ключа-путь:

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

... но это падает с *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'to-many key not allowed here.

Редактировать: Что касается возможного дубликата.

Когда я пытаюсь применить это для всех элементов NSSet я получаю следующее сообщение об ошибке: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath ALL messages.date not found in entity <NSSQLEntity Conversation id=1>'

Использования следующей сортировки дескриптора:

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

Возможный дубликат [Основные данные: NSPredicate для отношений «многие ко многим». (здесь не разрешен ключ «многие»)] (http://stackoverflow.com/questions/4217849/core-data-nspredicate-for-many-to-many-relationship-to-many-key-not-allowed) – chedabob

+0

Я нашел это. Но это для 'NSPredicate', а не' NSSortDescription'. Это работает только если вы хотите фильтровать вещи, а не сортировать, к сожалению. – Chris

+0

Он по-прежнему применяется. 'messages' является' NSSet', поэтому у него нет свойства 'date' для сортировки. – chedabob

ответ

-1
NSInteger type; 
NSDate* timestamp; 
NSString* username; 
NSString* session; 
NSString* body; 

NSFetchRequest * req = [[NSFetchRequest alloc] init]; 

[req setEntity:[NSEntityDescription entityForName:@"Message" 
inManagedObjectContext:context]]; 

[req setPredicate:[NSPredicate predicateWithFormat:@"conversation == %@", 
self]]; /* did that from a Conversation object.. */ 

NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"sent_date" 
ascending:NO]; 

[req setSortDescriptors:[NSArray arrayWithObject:sort]]; 

[sort release]; 

NSError * error = nil; 

NSArray * messages = [context executeFetchRequest:req error:&error]; 

[req release]; 

if ([messages count] > 0) { /* sanity check */ 

    return [messages objectAtIndex:0]; 

} 

return nil; 
+1

Вы прочитали вопрос ..?! – Chris

0

Создать категорию на 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.cbvTimeIntervalSinceStartOfDay" сделать фактическую сортировку. Например, я показываю класс Event и некоторый код, который выполняет сортировку.

@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") 
+0

Спасибо, но вам не хватает отношения 1: n между разговорами и сообщениями (на самом деле содержит дату). В этой проблеме я не могу получить доступ к свойству date в массиве сообщений из беседы. – Chris

0

То, что вы хотите сделать, это добавить Последнее сообщение дате атрибут разговора. Это позволит вам эффективно сортировать разговоры.

Это то, что называется денормализации. Вы должны убедиться, что это последнее сообщение date Поле обновлено. Существует много подходов.Один из них заключается в том, чтобы переопределить willSave() в разговоре и проверить, есть ли изменения в отношении сообщений или к любому Сообщения - при проверке этого вы должны быть уверены, что не вызывали каких-либо сбоев в работе объектов. Если что-то изменилось, вы затем обновите значение последнего сообщения .

Как построить Эффективные модели данных раздел в Performance главе нашей книги идет более подробно. https://www.objc.io/books/core-data/