Как использовать первый символ в качестве имени раздела

Я использую Core Data для представления таблицы, и я бы хотел использовать первую букву каждого из моих результатов в качестве заголовка раздела (чтобы я мог получить индекс раздела сбоку). Есть ли способ сделать это с помощью ключевого пути? Что-то вроде ниже, где я использую name.firstLetter как sectionNameKeyPath (к сожалению, это не работает).

Должен ли я сначала взять первую букву каждого результата и создать мои разделы? Лучше ли вставить новое свойство, чтобы просто удерживать первую букву и использовать ее как sectionNameKeyPath ?

 NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"name.firstLetter" cacheName:@"Root"]; 

Благодарю.

** EDIT: ** Я не уверен, что это имеет значение, но мои результаты – японцы, отсортированные по Катакане. Я хочу использовать эту Катакану в качестве индекса раздела.

Вы должны просто передать «имя» как sectionNameKeyPath. См. Этот ответ на вопрос «Основные данные, поддерживаемые UITableView с индексированием».

ОБНОВИТЬ
Это решение работает только в том случае, если вам просто нужно иметь быстрый скроллер заголовка индекса. В этом случае вы не будете отображать заголовки разделов. См. Ниже пример кода.

В противном случае я согласен с refulgentis, что переходное свойство является лучшим решением. Кроме того, при создании NSFetchedResultsController, разделNameKeyPath имеет это ограничение:

Если этот ключевой путь не совпадает с указанным первым дескриптором сортировки в fetchRequest, они должны генерировать одинаковые относительные порядки. Например, первый дескриптор сортировки в файле fetchRequest может указывать ключ для постоянного свойства; sectionNameKeyPath может указывать ключ для свойства переходного процесса, полученного из свойства persistent.

Реализованные в Boilerplate UITableViewDataSource с использованием NSFetchedResultsController:

 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return [[fetchedResultsController sections] count]; } - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { return [fetchedResultsController sectionIndexTitles]; } - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { return [fetchedResultsController sectionForSectionIndexTitle:title atIndex:index]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { id  sectionInfo = [[fetchedResultsController sections] objectAtIndex:section]; return [sectionInfo numberOfObjects]; } // Don't implement this since each "name" is its own section: //- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { // id  sectionInfo = [[fetchedResultsController sections] objectAtIndex:section]; // return [sectionInfo name]; //} 

ОБНОВЛЕНИЕ 2

Для нового свойства «uppercaseFirstLetterOfName» переходного процесса добавьте новый атрибут строки в применимый объект в модели и проверьте поле «переходный».

Существует несколько способов реализации getter. Если вы создаете / создаете подclassы, вы можете добавить его в файл реализации подclassа (.m).

В противном случае вы можете создать категорию в NSManagedObject (я помещаю это прямо вверху файла реализации controllerа представления, но вы можете разделить его между собственным заголовком и файлом реализации):

 @interface NSManagedObject (FirstLetter) - (NSString *)uppercaseFirstLetterOfName; @end @implementation NSManagedObject (FirstLetter) - (NSString *)uppercaseFirstLetterOfName { [self willAccessValueForKey:@"uppercaseFirstLetterOfName"]; NSString *aString = [[self valueForKey:@"name"] uppercaseString]; // support UTF-16: NSString *stringToReturn = [aString substringWithRange:[aString rangeOfComposedCharacterSequenceAtIndex:0]]; // OR no UTF-16 support: //NSString *stringToReturn = [aString substringToIndex:1]; [self didAccessValueForKey:@"uppercaseFirstLetterOfName"]; return stringToReturn; } @end 

Кроме того, в этой версии не забудьте передать ‘uppercaseFirstLetterOfName’ как sectionNameKeyPath:

 NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"uppercaseFirstLetterOfName" // this key defines the sections cacheName:@"Root"]; 

И, чтобы раскомментировать tableView:titleForHeaderInSection: в реализации UITableViewDataSource:

 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { id  sectionInfo = [[fetchedResultsController sections] objectAtIndex:section]; return [sectionInfo name]; } 

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

Во-первых, я определил свойство переходного процесса для объектов, которые я индексировал, имя firstLetterOfName, и написал геттер в файл .m для объекта. бывший

 - (NSString *)uppercaseFirstLetterOfName { [self willAccessValueForKey:@"uppercaseFirstLetterOfName"]; NSString *stringToReturn = [[self.name uppercaseString] substringToIndex:1]; [self didAccessValueForKey:@"uppercaseFirstLetterOfName"]; return stringToReturn; } 

Затем я настроил свой запрос / объекты выборки, чтобы использовать это свойство.

 NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:dataContext]; [request setEntity:entity]; [NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)]; NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; [request setSortDescriptors:sortDescriptors]; 

Боковое замечание, по поводу ничего: будьте осторожны с NSFetchedResultsController – он не совсем полностью испечен, но IMHO, и в любой ситуации, кроме простых случаев, перечисленных в документации, вам, вероятно, будет лучше делать это «старомодным» способом.

Я решил это с помощью UILocalizedIndexCollation, как указано в вопросе NSFetchedResultsController vs UILocalizedIndexedCollation

Элегантный способ состоит в том, чтобы сделать «firstLetter» переходным свойством, ОДНАКО на практике это медленно.

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

Быстрый, но неэлегантный способ заключается в создании непереходного свойства «firstLetter», которое вы обновляете каждый раз, когда вы устанавливаете свойство «name». Несколько способов сделать это: переопределить оценщик «setName:», переопределить «willSave», KVO.

См. Мой ответ на аналогичный вопрос здесь , в котором я описываю, как создавать локализованные индексы sectionKey, которые сохраняются (поскольку вы не можете сортировать по переходным атрибутам в NSFetchedResultsController).

Вот простое решение для obj-c, несколько лет и одного языка. Он работает и работает быстро в моем проекте.

Сначала я создал категорию на NSString, назвав файл NSString + Indexing. Я написал метод, который возвращает первую букву строки

 @implementation NSString (Indexing) - (NSString *)stringGroupByFirstInitial { if (!self.length || self.length == 1) return self; return [self substringToIndex:1]; } 

Затем я использовал этот метод в определении получаемого controllerа результата следующим образом

 _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"name.stringGroupByFirstInitial" cacheName:nil]; 

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

Однако, когда я пытаюсь сделать то же самое с Swift, он генерирует исключение, так как ему не нравится иметь функцию как путь ключа элемента (или вычисленное свойство строки – я тоже это пробовал). Если кто-то знает, как добиться того же самого в Свифте мне очень хотелось бы знать, как это сделать.

  • Как распределить приложение ios без проводов без управления UDID и перекомпиляции
  • Полужирный и нежирный текст в одном UILabel?
  • @synthesize vs @dynamic, каковы различия?
  • UISlider для управления AVAudioPlayer
  • Перемещение UIView (изображение и текст)
  • Правильный способ выхода из приложения iPhone?
  • глубокая изменчивая копия NSMutableDictionary
  • Декларация о свойствах и автоматическое резервирование хранилища
  • iOS 5: Как преобразовать Emoji в символ Юникода?
  • Cocoa Touch: как изменить цвет и толщину границ UIView?
  • Как проспать от сна программно, если крышка закрыта?
  • Interesting Posts
    Давайте будем гением компьютера.