Цель-C пользовательская сортировка - PullRequest
0 голосов
/ 13 декабря 2011

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

Вот что я хотел сделать:

У меня есть NSArrayController, который управляет NSManagedObjects (скажем, Thing). Эти объекты имеют свойство name, которое имеет тип NSString. Я хотел отсортировать массив контроллера массива, используя имя управляемых объектов. Обычный способ сортировки изменяемого массива строк должен выглядеть примерно так:

[myMutableArrayOfStrings sortUsingSelector:@selector(caseInsensitiveCompare:)];

или

NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
NSArray *descriptorArray = [NSArray arrayWithObject:sortDescriptor];
[myArrayController setSortDescriptors:descriptorArray];

Однако, если имена оказались числами, caseInsensitiveCompare: отсортирует 11 перед 8 (например). Кроме того, я хотел, чтобы имя a11b сортировалось ПОСЛЕ a8b, а это означало, что мне нужно было разбивать имена управляемых объектов на группы из цифровых и нецифровых символов, а затем сравнивать их по отдельности.

Я придумал создать категорию NSString.

заголовочный файл:

#import <Foundation/Foundation.h>

@interface NSString (MyString)

- (NSComparisonResult)myCustomCompare:(NSString *)anotherString;

@end

файл реализации:

#import "MyString.h"

@implementation NSString (MyString)

- (NSComparisonResult)myCustomCompare:(NSString *)anotherString {

  elaborate chopping up of strings into substrings..
  For each of the 2 strings I made an NSMutableArray.
  Then I determined if these substrings were NSNumbers, which have their own compare:, or NSStrings (caseInsensitiveCompare:)
  Then I return an NSComparisonResult (NSOrderedAscending, NSOrderedSame or NSOrderedDescending)

}

@end

Затем в файле реализации моего Thing ManagedObject я переопределил

- (NSComparisonResult)compare:(Thing *)anotherThing {

return [self.name  myCustomCompare:anotherThing.name];

}

Также необходимо импортировать MyString.h в класс Thing.

Теперь, используя

[[myArrayController arrangedObjects] sortUsingSelector:@selector(compare:)];

работает как шарм.

Только одна вещь, которая беспокоила меня. Если свойство имени Thing будет содержать десятичные числа, как, например, a1.4b и a1.39b, как я смогу изолировать их от имени? (a1.4b будет неправильно отсортирован до a1.39b) Что еще хуже, пользователь может ввести имя вещи как 1.3.55 ...

...