NSFetchedResultsController и UILocalizedIndexCollation
Я хочу заселить UITableView
с помощью NSFetchedResultsController
, Я хочу, чтобы в табличном представлении были разделы для первой буквы в названии объекта. Табличное представление также должно иметь индексный список справа.
Вот как выглядит моя сущность:
@interface Book : NSManagedObject
@property (nonatomic, copy) NSString *title;
@end
Мой первый план состоял в том, чтобы иметь временное свойство, которое возвращало первую букву в заголовке:
- (NSString *)firstLetter
{
// Edge-cases checking code not included
return [self.title substringToIndex:1];
}
Проблема в том, что он даст вам разные разделы для "2" и "3", например, я хочу, чтобы все цифры и символы в одном разделе назывались "#", так же, как UILocalizedIndexCollation
дает тебе.
Но какие буквы должны быть в категории "#"? Конечно, это зависит от языка, на английском языке "Ö" должно быть в другой категории, но на шведском языке это должно быть в своей собственной категории. Поэтому я подумал, что, может быть, я должен просто использовать NSLocalizedIndexCollation
вместо. Вот этот код:
- (void)recalculateSectionizedBooks
{
SEL selector = @selector(title);
NSInteger sectionTitlesCount = [[[UILocalizedIndexedCollation currentCollation] sectionTitles] count];
NSMutableArray *mutableSections = [NSMutableArray arrayWithCapacity:sectionTitlesCount];
for (NSUInteger idx = 0; idx < sectionTitlesCount; idx++)
{
[mutableSections addObject:[NSMutableArray array]];
}
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Book"];
NSError *error = nil;
NSArray *result = [self.context executeFetchRequest:request
error:&error];
if (error)
{
NSLog(@"Error fetching: %@", error);
}
for (Book *book in result)
{
NSInteger sectionNumber = [[UILocalizedIndexedCollation currentCollation] sectionForObject:book
collationStringSelector:selector];
[mutableSections[sectionNumber] addObject:book];
}
for (NSUInteger idx = 0; idx < sectionTitlesCount; idx++)
{
NSArray *objectsForSection = mutableSections[idx];
mutableSections[idx] = [[UILocalizedIndexedCollation currentCollation] sortedArrayFromArray:objectsForSection
collationStringSelector:selector];
}
self.sectionizedBooks = mutableSections;
}
Это называется в -viewWillAppear:
после этого я перезагружаю свой вид таблицы. Метод источника данных правильно настроен, а также обеспечивает отсутствие пустых разделов.
Это решение имеет две проблемы. Во-первых, для работы требуется огромное количество кода (гораздо больше, чем фрагмент, который я вам показал). Вторая, более серьезная проблема заключается в том, что производительность очень плохая. Каждый раз, когда представление отображается, разделы должны быть пересчитаны, потому что что-то, влияющее на это, могло измениться. Это заняло 30 секунд с 10 тысячами книг, что недопустимо.
Я думаю, что мне нужно решение, которое сочетает в себе NSFetchedResultsController
а также UILocalizedCollation
умным способом. Вот что мне нужно из решения:
- Наличие книг в разделах на основе первой буквы в заголовке
- "Другая" категория ('#') должна существовать в конце
- Нет пустых разделов
- Индексный список справа со всеми возможными буквами + '#' в конце
- Высокая производительность, по крайней мере, после первого просмотра