Как мне отсортировать NSMutableArray с пользовательскими объектами в нем?

То, что я хочу сделать, кажется довольно простым, но я не могу найти ответы в Интернете. У меня есть NSMutableArrayобъекты, и скажем, они являются объектами «Персона». Я хочу отсортировать NSMutableArrayпо Person.birthDate, который является NSDate.

Я думаю, что это как-то связано с этим методом:

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];

В Java я хотел бы, чтобы мой объект реализовывал Comparable, или использовал Collections.sort со встроенным пользовательским компаратором ... как же это сделать в Objective-C?

30.04.2009 06:10:56
27 ОТВЕТОВ
РЕШЕНИЕ

Сравнить метод

Либо вы реализуете метод сравнения для вашего объекта:

- (NSComparisonResult)compare:(Person *)otherObject {
    return [self.birthDate compare:otherObject.birthDate];
}

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(compare:)];

NSSortDescriptor (лучше)

или обычно даже лучше:

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                           ascending:YES];
NSArray *sortedArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];

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

Блоки (блестящие!)

Начиная с Mac OS X 10.6 и iOS 4, есть также возможность сортировки по блокам:

NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    NSDate *first = [(Person*)a birthDate];
    NSDate *second = [(Person*)b birthDate];
    return [first compare:second];
}];

Представление

-compare:И блочные методы на основе будет совсем немного быстрее, в общем, чем при использовании в NSSortDescriptorкачестве последнего полагается на КВЦ. Основным преимуществом NSSortDescriptorметода является то, что он предоставляет способ определения порядка сортировки с использованием данных, а не кода, что позволяет, например, легко настроить объекты, чтобы пользователи могли сортировать их NSTableView, щелкая строку заголовка.

2295
12.06.2017 14:50:16
В первом примере есть ошибка: вы сравниваете переменную экземпляра birthDate в одном объекте с самим другим объектом, а не с его переменной birthDate.
Martin Gjaldbaek 17.05.2011 08:52:53
@ Мартин: Спасибо! Забавно, что никто не заметил, прежде чем я получил 75 голосов за это.
Georg Schölly 17.05.2011 11:18:17
Поскольку это общепринятый ответ, и поэтому, вероятно, большинство пользователей считают его окончательным, было бы полезно добавить третий, основанный на блоках пример, чтобы пользователи знали, что он тоже существует.
jpswain 2.12.2011 20:30:26
@ orange80: я попробовал это. У меня больше нет Mac, поэтому было бы неплохо, если бы вы взглянули на код.
Georg Schölly 4.12.2011 20:25:21
Если у вас есть, NSMutableArrayя предпочитаю использовать методы sortUsingDescriptors, sortUsingFunctionили sortUsingSelector. Поскольку массив изменчив, мне обычно не нужна отсортированная копия.
Stephan 6.08.2012 06:01:43

Ваши Personобъекты должны реализовать метод, скажем, compare:который принимает другой Personобъект, и возвращать в NSComparisonResultсоответствии с отношениями между двумя объектами.

Тогда вы позвоните sortedArrayUsingSelector:с, @selector(compare:)и это должно быть сделано.

Есть и другие способы, но, насколько я знаю, не существует Cocoa-эквивалента Comparableинтерфейса. Использование sortedArrayUsingSelector:, вероятно, самый безболезненный способ сделать это.

17
30.04.2009 06:25:14

Смотрите NSMutableArrayметодsortUsingFunction:context:

Вам нужно настроить функцию сравнения, которая принимает два объекта (типа Person, поскольку вы сравниваете два Personобъекта) и параметр контекста .

Два объекта являются просто экземплярами Person. Третий объект - это строка, например @ "birthDate".

Эта функция возвращает NSComparisonResult: Возвращает , NSOrderedAscendingесли PersonA.birthDate< PersonB.birthDate. Он вернется, NSOrderedDescendingесли PersonA.birthDate> PersonB.birthDate. Наконец, он вернется, NSOrderedSameесли PersonA.birthDate== PersonB.birthDate.

Это грубый псевдокод; вам нужно будет уточнить, что означает, что одна дата «меньше», «больше» или «равна» другой дате (например, сравнение секунд с начала эпохи и т. д.):

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  if ([firstPerson birthDate] < [secondPerson birthDate])
    return NSOrderedAscending;
  else if ([firstPerson birthDate] > [secondPerson birthDate])
    return NSOrderedDescending;
  else 
    return NSOrderedSame;
}

Если вы хотите что-то более компактное, вы можете использовать троичные операторы:

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  return ([firstPerson birthDate] < [secondPerson birthDate]) ? NSOrderedAscending : ([firstPerson birthDate] > [secondPerson birthDate]) ? NSOrderedDescending : NSOrderedSame;
}

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

108
13.06.2016 17:21:52
Использование sortUsingFunction: context:, вероятно, является наиболее понятным и, безусловно, самым нечитаемым способом.
Georg Schölly 30.04.2009 06:28:40
В этом нет ничего плохого, но я думаю, что теперь есть намного лучшие альтернативы.
Georg Schölly 30.04.2009 06:43:54
Возможно, но я не думаю, что это было бы менее читабельным для кого-то из Java-фона, который может искать что-то похожее на абстрактный класс Java-компаратора, который реализует сравнение (Тип obj1, Тип obj2).
Alex Reynolds 30.04.2009 06:51:51
Я понимаю, что некоторые из вас ищут любую причину, чтобы критиковать этот совершенно прекрасный ответ, даже если эта критика имеет очень мало технических достоинств. Weird.
Alex Reynolds 1.05.2009 17:59:13
@ Яр: Либо вы можете использовать решение, которое я предоставил в первом абзаце, либо использовать несколько дескрипторов сортировки. sortedArrayUsingDescriptors: принимает массив дескрипторов сортировки в качестве аргумента.
Georg Schölly 17.12.2010 11:38:19

Во втором ответе Георга Шолли пропущен шаг , но тогда он работает нормально.

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                              ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

// добавил 's', потому что когда я копировал и вставлял, было потрачено время, и это не удалось без 's' в sortedArrayUsingDescriptors

20
19.04.2020 14:49:07
Вызов метода на самом деле "sortedArrayUsingDescriptors:", с 's' в конце.
CIFilter 13.05.2009 19:58:37

Для NSMutableArray, используйте sortUsingSelectorметод. Это сортирует это место, не создавая новый экземпляр.

8
3.06.2013 07:23:14
Просто обновление: Я тоже искал что - то , что отсортированный изменяемый массив на месте, там сейчас «sortUsing» эквивалентные методы для всех «sortedArrayUsing» методы , как ИО 7. Такие , как sortUsingComparator:.
jmathew 17.11.2013 19:01:18

Я перепробовал все, но это сработало для меня. В классе у меня есть другой класс с именем " crimeScene", и я хочу отсортировать по свойству " crimeScene".

Это работает как шарм:

NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"crimeScene.distance" ascending:YES];
[self.arrAnnotations sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
26
24.12.2016 07:40:28

Начиная с iOS 4 вы также можете использовать блоки для сортировки.

Для этого конкретного примера я предполагаю, что у объектов в вашем массиве есть метод 'position', который возвращает NSInteger.

NSArray *arrayToSort = where ever you get the array from... ;
NSComparisonResult (^sortBlock)(id, id) = ^(id obj1, id obj2) 
{
    if ([obj1 position] > [obj2 position]) 
    { 
        return (NSComparisonResult)NSOrderedDescending;
    }
    if ([obj1 position] < [obj2 position]) 
    {
        return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
};
NSArray *sorted = [arrayToSort sortedArrayUsingComparator:sortBlock];

Примечание: отсортированный массив будет автоматически освобожден.

29
13.06.2016 09:52:16

Я сделал это в iOS 4, используя блок. Пришлось привести элементы моего массива из id к типу моего класса. В данном случае это был класс Score с свойством points.

Также вам нужно решить, что делать, если элементы вашего массива имеют неправильный тип, для этого примера я только что вернулся NSOrderedSame, однако в моем коде я исключение.

NSArray *sorted = [_scores sortedArrayUsingComparator:^(id obj1, id obj2){
    if ([obj1 isKindOfClass:[Score class]] && [obj2 isKindOfClass:[Score class]]) {
        Score *s1 = obj1;
        Score *s2 = obj2;

        if (s1.points > s2.points) {
            return (NSComparisonResult)NSOrderedAscending;
        } else if (s1.points < s2.points) {
            return (NSComparisonResult)NSOrderedDescending;
        }
    }

    // TODO: default is the same?
    return (NSComparisonResult)NSOrderedSame;
}];

return sorted;

PS: это сортировка по убыванию.

62
3.06.2013 07:22:00
Вам на самом деле не нужны приведения «(Score *)», вы можете просто выполнить «Score * s1 = obj1;» потому что id с радостью приведёт к чему угодно без предупреждения от компилятора :-)
jpswain 2.12.2011 20:28:46
right orange80 downcastingне требует приведения перед слабой переменной.
thesummersign 3.05.2012 10:48:58
Вы должны сортировать ноль против не-ноль в верхней или нижней части последовательно, поэтому конец умолчанию возвращают может бытьreturn ((!obj1 && !obj2) ? NSOrderedSame : (obj1 ? NSOrderedAscending : NSOrderedDescending))
Scott Corscadden 8.08.2012 18:53:47
хех Крис, я пробовал этот код, я обновлял свою программу ... впервые я исправляю работу, получаю вывод в порядке убывания ... но когда я обновляю (выполняю тот же код с теми же данными), это изменилось порядок, он не по убыванию .. Скажем, у меня 4 объекта в моем массиве, 3 объекта с одинаковыми данными, 1 отличается.
Nikesh K 13.09.2012 07:12:50
Если вы действительно ожидаете объекты, которые не относятся к классу «Оценка», вам нужно отсортировать их немного более тщательно. В противном случае вы столкнетесь с ситуацией, когда другое == оценка1 <оценка2 == другое, что является непоследовательным и может привести к проблемам. Вы можете вернуть значение, которое подразумевает сортировку объектов Score перед всеми остальными объектами, а все остальные объекты сортируются равными друг другу.
gnasher729 17.02.2014 14:57:11
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

Спасибо работает нормально ...

19
31.01.2016 18:00:00

Блоки iOS 4 спасут вас :)

featuresArray = [[unsortedFeaturesArray sortedArrayUsingComparator: ^(id a, id b)  
{
    DMSeatFeature *first = ( DMSeatFeature* ) a;
    DMSeatFeature *second = ( DMSeatFeature* ) b;

    if ( first.quality == second.quality )
        return NSOrderedSame;
    else
    {
        if ( eSeatQualityGreen  == m_seatQuality || eSeatQualityYellowGreen == m_seatQuality || eSeatQualityDefault  == m_seatQuality )
        {
            if ( first.quality < second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        }
        else // eSeatQualityRed || eSeatQualityYellow
        {
            if ( first.quality > second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        } 
    }
}] retain];

http://sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html немного описания

9
8.08.2016 12:21:10

Я использовал sortUsingFunction :: в некоторых моих проектах:

int SortPlays(id a, id b, void* context)
{
    Play* p1 = a;
    Play* p2 = b;
    if (p1.score<p2.score) 
        return NSOrderedDescending;
    else if (p1.score>p2.score) 
        return NSOrderedAscending;
    return NSOrderedSame;
}

...
[validPlays sortUsingFunction:SortPlays context:nil];
5
31.01.2016 18:00:53

Сортировка NSMutableArrayочень проста:

NSMutableArray *arrayToFilter =
     [[NSMutableArray arrayWithObjects:@"Photoshop",
                                       @"Flex",
                                       @"AIR",
                                       @"Flash",
                                       @"Acrobat", nil] autorelease];

NSMutableArray *productsToRemove = [[NSMutableArray array] autorelease];

for (NSString *products in arrayToFilter) {
    if (fliterText &&
        [products rangeOfString:fliterText
                        options:NSLiteralSearch|NSCaseInsensitiveSearch].length == 0)

        [productsToRemove addObject:products];
}
[arrayToFilter removeObjectsInArray:productsToRemove];
3
31.01.2016 18:02:06

Если вы просто сортируете массив NSNumbers, вы можете отсортировать их одним вызовом:

[arrayToSort sortUsingSelector: @selector(compare:)];

Это работает, потому что объекты в массиве ( NSNumberобъекты) реализуют метод сравнения. Вы можете сделать то же самое для NSStringобъектов или даже для массива пользовательских объектов данных, которые реализуют метод сравнения.

Вот пример кода с использованием блоков компаратора. Он сортирует массив словарей, где каждый словарь включает число в ключе «sort_key».

#define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
 ^(id obj1, id obj2) 
  {
  NSInteger value1 = [[obj1 objectForKey: SORT_KEY] intValue];
  NSInteger value2 = [[obj2 objectForKey: SORT_KEY] intValue];
  if (value1 > value2) 
{
  return (NSComparisonResult)NSOrderedDescending;
  }

  if (value1 < value2) 
{
  return (NSComparisonResult)NSOrderedAscending;
  }
    return (NSComparisonResult)NSOrderedSame;
 }];

Приведенный выше код проходит через процесс получения целочисленного значения для каждого ключа сортировки и сравнения их в качестве иллюстрации того, как это сделать. Поскольку NSNumberобъекты реализуют метод сравнения, его можно переписать гораздо проще:

 #define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
^(id obj1, id obj2) 
 {
  NSNumber* key1 = [obj1 objectForKey: SORT_KEY];
  NSNumber* key2 = [obj2 objectForKey: SORT_KEY];
  return [key1 compare: key2];
 }];

или тело компаратора может быть отогнано до 1 строки:

  return [[obj1 objectForKey: SORT_KEY] compare: [obj2 objectForKey: SORT_KEY]];

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

6
3.06.2013 07:22:57
-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted 
{
  NSArray *sortedArray;
  sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
  {
    return [a compare:b];
 }];
 return [sortedArray mutableCopy];
}
4
11.01.2013 11:32:29
зачем передавать в изменяемый массив, когда возвращается новый массив. зачем вообще создавать обертку?
vikingosegundo 10.01.2013 15:40:36

Я создал небольшую библиотеку методов категорий, названную Linq to ObjectiveC , которая упрощает подобные вещи. Используя метод сортировки с ключевым селектором, вы можете сортировать birthDateследующим образом:

NSArray* sortedByBirthDate = [input sort:^id(id person) {
    return [person birthDate];
}]
5
6.03.2013 08:29:13
Вы должны назвать это « LINQ to Objective-C ».
Peter Mortensen 28.11.2017 13:59:19

Я только что сделал многоуровневую сортировку на основе пользовательских требований.

// сортируем значения

    [arrItem sortUsingComparator:^NSComparisonResult (id a, id b){

    ItemDetail * itemA = (ItemDetail*)a;
    ItemDetail* itemB =(ItemDetail*)b;

    //item price are same
    if (itemA.m_price.m_selling== itemB.m_price.m_selling) {

        NSComparisonResult result=  [itemA.m_itemName compare:itemB.m_itemName];

        //if item names are same, then monogramminginfo has to come before the non monograme item
        if (result==NSOrderedSame) {

            if (itemA.m_monogrammingInfo) {
                return NSOrderedAscending;
            }else{
                return NSOrderedDescending;
            }
        }
        return result;
    }

    //asscending order
    return itemA.m_price.m_selling > itemB.m_price.m_selling;
}];

https://sites.google.com/site/greateindiaclub/mobil-apps/ios/multilevelsortinginiosobjectivec

5
13.12.2014 03:06:46
NSMutableArray *stockHoldingCompanies = [NSMutableArray arrayWithObjects:fortune1stock,fortune2stock,fortune3stock,fortune4stock,fortune5stock,fortune6stock , nil];

NSSortDescriptor *sortOrder = [NSSortDescriptor sortDescriptorWithKey:@"companyName" ascending:NO];

[stockHoldingCompanies sortUsingDescriptors:[NSArray arrayWithObject:sortOrder]];

NSEnumerator *enumerator = [stockHoldingCompanies objectEnumerator];

ForeignStockHolding *stockHoldingCompany;

NSLog(@"Fortune 6 companies sorted by Company Name");

    while (stockHoldingCompany = [enumerator nextObject]) {
        NSLog(@"===============================");
        NSLog(@"CompanyName:%@",stockHoldingCompany.companyName);
        NSLog(@"Purchase Share Price:%.2f",stockHoldingCompany.purchaseSharePrice);
        NSLog(@"Current Share Price: %.2f",stockHoldingCompany.currentSharePrice);
        NSLog(@"Number of Shares: %i",stockHoldingCompany.numberOfShares);
        NSLog(@"Cost in Dollars: %.2f",[stockHoldingCompany costInDollars]);
        NSLog(@"Value in Dollars : %.2f",[stockHoldingCompany valueInDollars]);
    }
    NSLog(@"===============================");
-2
7.04.2014 23:26:05

Вы можете использовать следующий общий метод для ваших целей. Это должно решить вашу проблему.

//Called method
-(NSMutableArray*)sortArrayList:(NSMutableArray*)arrDeviceList filterKeyName:(NSString*)sortKeyName ascending:(BOOL)isAscending{
    NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:sortKeyName ascending:isAscending];
    [arrDeviceList sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
    return arrDeviceList;
}

//Calling method
[self sortArrayList:arrSomeList filterKeyName:@"anything like date,name etc" ascending:YES];
7
29.09.2015 20:56:35

Сортировка с использованием NSComparator

Если мы хотим отсортировать пользовательские объекты, нам нужно предоставить данные NSComparator, которые используются для сравнения пользовательских объектов. Блок возвращает NSComparisonResultзначение для обозначения порядка двух объектов. Поэтому для сортировки всего массива NSComparatorиспользуется следующий способ.

NSArray *sortedArray = [employeesArray sortedArrayUsingComparator:^NSComparisonResult(Employee *e1, Employee *e2){
    return [e1.firstname compare:e2.firstname];    
}];

Сортировка с использованием NSSortDescriptor
Предположим, в качестве примера, что у нас есть массив, содержащий экземпляры пользовательского класса, у Employee есть атрибуты имя, фамилия и возраст. В следующем примере показано, как создать NSSortDescriptor, который можно использовать для сортировки содержимого массива в возрастающем порядке по ключу возраста.

NSSortDescriptor *ageDescriptor = [[NSSortDescriptor alloc] initWithKey:@"age" ascending:YES];
NSArray *sortDescriptors = @[ageDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

Сортировка с использованием пользовательских сравнений
Имена - это строки, и при сортировке строк для представления пользователю всегда следует использовать локализованное сравнение. Часто вы также хотите выполнить сравнение без учета регистра. Вот пример с (localizedStandardCompare :), чтобы упорядочить массив по фамилии и имени.

NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"lastName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSSortDescriptor * firstNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"firstName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSArray *sortDescriptors = @[lastNameDescriptor, firstNameDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

Для справки и подробного обсуждения, пожалуйста, обратитесь: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.html
http://www.ios-blog.co.uk/tutorials / Objective-C / как к своего рода-NSArray-с-пользовательских-объектов /

2
17.06.2016 05:12:49

В моем случае я использую «sortedArrayUsingComparator» для сортировки массива. Посмотрите на приведенный ниже код.

contactArray = [[NSArray arrayWithArray:[contactSet allObjects]] sortedArrayUsingComparator:^NSComparisonResult(ContactListData *obj1, ContactListData *obj2) {
    NSString *obj1Str = [NSString stringWithFormat:@"%@ %@",obj1.contactName,obj1.contactSurname];
    NSString *obj2Str = [NSString stringWithFormat:@"%@ %@",obj2.contactName,obj2.contactSurname];
    return [obj1Str compare:obj2Str];
}];

Также мой объект,

@interface ContactListData : JsonData
@property(nonatomic,strong) NSString * contactName;
@property(nonatomic,strong) NSString * contactSurname;
@property(nonatomic,strong) NSString * contactPhoneNumber;
@property(nonatomic) BOOL isSelected;
@end
1
28.11.2017 14:00:21

Протоколы и функциональное программирование Swift делают это очень простым: нужно просто привести свой класс в соответствие с протоколом Comparable, реализовать методы, требуемые протоколом, а затем использовать отсортированную (by:) функцию высокого порядка для создания отсортированного массива без необходимости использования изменяемые массивы кстати.

class Person: Comparable {
    var birthDate: NSDate?
    let name: String

    init(name: String) {
        self.name = name
    }

    static func ==(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate === rhs.birthDate || lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedSame
    }

    static func <(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedAscending
    }

    static func >(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedDescending
    }

}

let p1 = Person(name: "Sasha")
p1.birthDate = NSDate() 

let p2 = Person(name: "James")
p2.birthDate = NSDate()//he is older by miliseconds

if p1 == p2 {
    print("they are the same") //they are not
}

let persons = [p1, p2]

//sort the array based on who is older
let sortedPersons = persons.sorted(by: {$0 > $1})

//print sasha which is p1
print(persons.first?.name)
//print James which is the "older"
print(sortedPersons.first?.name)
2
27.03.2017 22:14:35

Сортировать массив в Swift


Для Swiftyчеловека ниже очень чистая техника для достижения поставленной цели в глобальном масштабе. Давайте рассмотрим пример пользовательского класса, Userкоторый имеет некоторые атрибуты.

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
}

Теперь у нас есть массив, который нам нужно отсортировать по createdDateвозрастанию и / или убыванию. Итак, давайте добавим функцию для сравнения дат.

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
    func checkForOrder(_ otherUser: User, _ order: ComparisonResult) -> Bool {
        if let myCreatedDate = self.createdDate, let othersCreatedDate = otherUser.createdDate {
            //This line will compare both date with the order that has been passed.
            return myCreatedDate.compare(othersCreatedDate) == order
        }
        return false
    }
}

Теперь давайте иметь extensionв Arrayтечение User. Проще говоря, давайте добавим некоторые методы только для тех массивов, в которых есть только Userобъекты.

extension Array where Element: User {
    //This method only takes an order type. i.e ComparisonResult.orderedAscending
    func sortUserByDate(_ order: ComparisonResult) -> [User] {
        let sortedArray = self.sorted { (user1, user2) -> Bool in
            return user1.checkForOrder(user2, order)
        }
        return sortedArray
    }
}

Использование по возрастанию

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Использование по убыванию

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Использование для того же заказа

let sortedArray = someArray.sortUserByDate(.orderedSame)

Выше метод в extensionбудет доступен только если Arrayимеет тип [User]||Array<User>

1
24.03.2018 21:20:34

Вы должны создать sortDescriptor, а затем вы можете отсортировать массив nsmutablearray, используя sortDescriptor, как показано ниже.

 let sortDescriptor = NSSortDescriptor(key: "birthDate", ascending: true, selector: #selector(NSString.compare(_:)))
 let array = NSMutableArray(array: self.aryExist.sortedArray(using: [sortDescriptor]))
 print(array)
1
12.04.2018 10:32:49

Вы используете NSSortDescriptor для сортировки NSMutableArray с пользовательскими объектами

 NSSortDescriptor *sortingDescriptor;
 sortingDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                       ascending:YES];
 NSArray *sortArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];
4
14.06.2018 09:21:27

Используйте как это для вложенных объектов,

NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"lastRoute.to.lastname" ascending:YES selector:@selector(caseInsensitiveCompare:)];
NSMutableArray *sortedPackages = [[NSMutableArray alloc]initWithArray:[packages sortedArrayUsingDescriptors:@[sortDescriptor]]];

lastRoute - это один объект, и этот объект содержит объект to, этот объект содержит строковые значения lastname.

1
24.04.2019 13:19:50

Swift версия: 5.1

Если у вас есть пользовательская структура или класс, и вы хотите отсортировать их произвольно, вам следует вызвать метод sort () с использованием завершающего замыкания, которое сортирует по указанному вами полю. Вот пример использования массива пользовательских структур, который сортирует по определенному свойству:

    struct User {
        var firstName: String
    }

    var users = [
        User(firstName: "Jemima"),
        User(firstName: "Peter"),
        User(firstName: "David"),
        User(firstName: "Kelly"),
        User(firstName: "Isabella")
    ]

    users.sort {
        $0.firstName < $1.firstName
    }

Если вы хотите вернуть отсортированный массив, а не отсортировать его на месте, используйте sorted () следующим образом:

    let sortedUsers = users.sorted {
        $0.firstName < $1.firstName
    }
1
20.02.2020 13:23:44
  let sortedUsers = users.sorted {
    $0.firstName < $1.firstName
 }
1
16.03.2020 13:31:05