Сортировать NSDictionarray в NSMutableArray по NSDate

#objective-c #ios #cocoa-touch #nsdate

#objective-c #iOS #cocoa-touch #nsdate

Вопрос:

У меня есть NSMutableArray со словарями, все dict содержат NSDate в форме NSDate с ключом ‘Date’. Я хочу отсортировать nsdictionararray по датам. Итак, например, у меня есть следующее состояние массива:

 Dict
   Date
      20.06.1996 23:30
Dict
   Date
      04.10.2011 19:00
Dict
   Date
      20.06.1956 23:39
  

И я хочу отсортировать его, чтобы он выглядел так:

 Dict
   Date
      20.06.1956 23:39
Dict
   Date
      20.06.1996 23:30
Dict
   Date
      04.10.2011 19:00
  

Я уже экспериментировал с NSSortDescriptor, но безуспешно…

Обновить:

Мне удалось отсортировать даты, но я столкнулся с такой проблемой: в dicts есть не только даты, но и другие объекты, и что делает мой код, так это только переключение значений даты между dicts вместо переключения полных dicts. При этом другим значениям в dicts присваивается неправильная дата, что очень плохо. Кто-нибудь может мне помочь? Вот мой код:

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"savedData.daf"];
NSMutableArray *d = [NSMutableArray arrayWithContentsOfFile:path];



for (int ii = 0; ii < [d count]; ii  ) {
    NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
    if (is24h) {
        [dateFormatter setDateFormat:@"dd.MM.yyyy HH:mm"];
    }
    else {
        [dateFormatter setDateFormat:@"dd.MM.yyyy hh:mm a"];
    }
    [dateFormatter setLocale:[NSLocale currentLocale]];
    NSDate *dat = [dateFormatter dateFromString:[[d valueForKey:@"Date"] objectAtIndex:ii]];
    NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init];
    NSDictionary *oldDict = (NSDictionary *)[d objectAtIndex:ii];
    [newDict addEntriesFromDictionary:oldDict];
    [newDict setObject:dat forKey:@"Date"];
    [d replaceObjectAtIndex:ii withObject:newDict];
    [newDict release];
}


NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"Date" ascending:YES];
NSArray *sorters = [[NSArray alloc] initWithObjects:sorter, nil];
[sorter release];
NSMutableArray *sorted = [NSMutableArray arrayWithArray:[d sortedArrayUsingDescriptors:sorters]];
[sorters release];
NSLog(@"%@",sorted);
for (int ii = 0; ii < [sorted count]; ii  ) {
    NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
    if (is24h) {
        [dateFormatter setDateFormat:@"dd.MM.yyyy HH:mm"];
    }
    else {
        [dateFormatter setDateFormat:@"dd.MM.yyyy hh:mm a"];
    }
    [dateFormatter setLocale:[NSLocale currentLocale]];
    NSString *sr = [dateFormatter stringFromDate:[[sorted valueForKey:@"Date"] objectAtIndex:ii]];
    NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init];
    NSDictionary *oldDict = (NSDictionary *)[d objectAtIndex:ii];
    [newDict addEntriesFromDictionary:oldDict];
    [newDict setObject:sr forKey:@"Date"];
    [sorted replaceObjectAtIndex:ii withObject:newDict];
    [newDict release];
}
NSLog(@"before: %@"
      ""
      "after: %@",d,sorted);
[sorted writeToFile:path atomically:YES];
  

Комментарии:

1. Вы должны опубликовать код, который вы не смогли заставить работать.

2. Я в замешательстве. Содержат ли они NSDates или NSStrings? Вы говорите и то, и другое, но объект не может быть одновременно NSDate и NSString .

3. Это NSStrings, извините за это!

Ответ №1:

Есть много способов сделать это, один из них — использовать объекты NSDate вместо NSStrings (или NSStrings, отформатированные в соответствии с ISO 8601, чтобы лексикографическая сортировка соответствовала желаемой сортировке). Тогда вы могли бы сделать:

 NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"Date" 
                                                             ascending:YES];
[array sortUsingDescriptors:[NSArray arrayWithObject:descriptor]];
  

Или, если вы не можете (или не хотите) изменять свои данные, вы всегда можете выполнить сортировку с помощью блока:

 [array sortUsingComparator:^(id dict1, id dict2) {
    NSDate *date1 = // create NSDate from dict1's Date;
    NSDate *date2 = // create NSDate from dict2's Date;
    return [date1 compare:date2];
}];
  

Конечно, это, вероятно, будет медленнее, чем первый подход, поскольку обычно в итоге вы создаете более n объектов NSDate.

Комментарии:

1. Большое спасибо, это действительно помогло мне, я столкнулся с другой проблемой, это объясняется в обновленном вопросе, пожалуйста, ознакомьтесь с ним и попытайтесь мне помочь 🙂

2. Если оставить в стороне много ненужного кода, замена [d objectAtIndex:ii] на [sorted objectAtIndex:ii] должна решить вашу проблему.

3. приветствия! Вот и все! А как насчет ненужного кода? 🙂

4. Ваш код излишне сложен. Вам не нужно копировать NSMutableDictionaries (они изменчивы ), вам не нужно конвертировать даты туда и обратно и т. Д.

5. Но мне нужно преобразовать строки в даты, чтобы отсортировать их, а затем мне нужно, чтобы они были преобразованы обратно в строки, потому что все мое приложение работает только со строками!

Ответ №2:

Есть несколько вариантов, один из которых — поместить объекты NSDate в словарь.

Одна из проблем при сравнении строк заключается в том, что вы не можете просто выполнить сравнение строк, потому что год не находится в самом значимом элементе строки.

Итак, вам нужно будет написать метод сравнения для использования с:

 - (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr
  

или, возможно:

 - (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context
  

Компаратору необходимо будет обработать dd.mm.yyyy hh:mm строковый формат.

Другие варианты включают добавление другого словарного ключа с представлением NSDate и сортировку по нему.

Комментарии:

1. Не могли бы вы дать мне еще немного кода, пожалуйста, я не могу понять это так!