Неамериканские символы в заголовках разделов для UITableView
Я добавил список разделов для простого приложения Core Data iPhone.
Я следил за этим вопросом, чтобы создать его - Как использовать первый символ как имя раздела, но в моем списке также содержатся элементы, начинающиеся с символов за пределами AZ, особенно Å, Ä и... используется здесь в Швеции.
Теперь проблема заключается в том, что когда в представлении таблицы отображается список разделов, три последних символа рисуются неправильно. См. Изображение ниже
Кажется, мой лучший вариант прямо сейчас - это отсортировать эти элементы под "Z"
if ([letter isEqual:@"Å"] ||
[letter isEqual:@"Ä"] ||
[letter isEqual:@"Ö"])
letter = @"Z";
Кто-то, кто понял это?
И пока я нахожусь... "Å", "Ä" и "Ö" следует сортировать в этом порядке, но сортируются как "Ä", "Å" и "Ö" по данным Core NSSortDescriptor
. Я попытался установить селектор на localizedCaseInsensitiveCompare:
, но это дает ошибку out of order section name 'Ä. Objects must be sorted by section name'
. Видите это тоже?
Ответы
Ответ 1
Итак, я не мог отпустить этот и нашел следующее:
Что вам нужно сделать в этом случае, называется "Unicode Normalization Form D". Это больше объясняется в http://unicode.org/reports/tr15/ (предупреждение, длинный и сухой документ)
Вот функция, которая выполняет декомпозицию, а затем отфильтровывает все диакритики. Вы можете использовать это для преобразования Äpple в Apple, а затем использовать первую букву для создания индекса.
- (NSString*) decomposeAndFilterString: (NSString*) string
{
NSMutableString *decomposedString = [[string decomposedStringWithCanonicalMapping] mutableCopy];
NSCharacterSet *nonBaseSet = [NSCharacterSet nonBaseCharacterSet];
NSRange range = NSMakeRange([decomposedString length], 0);
while (range.location > 0) {
range = [decomposedString rangeOfCharacterFromSet:nonBaseSet
options:NSBackwardsSearch range:NSMakeRange(0, range.location)];
if (range.length == 0) {
break;
}
[decomposedString deleteCharactersInRange:range];
}
return [decomposedString autorelease];
}
(я нашел этот код в списке рассылки, забыли его, но я взял его и немного исправил)
Ответ 2
Я испытываю ту же проблему, о которой сообщалось в исходном вопросе, то есть расширенные символы (за пределами Unicode page 0), которые неправильно отображаются в строке индекса.
Хотя я, кажется, подаю NSFetchedResultsController с правильными одиночными символами символа Юникода, то, что я получаю в обратном доступе к свойству 'sectionIndexTitles', это те же самые символы, у которых старший байт установлен на 0; например символ \u30a2 (KATAKANA LETTER A) становится \u00a2 (CENT SIGN).
Я не уверен, является ли это ошибкой в методе sectionIndexTitleForSectionName: NSFetchedResultsController или моя собственная ошибка где-то в другом месте, однако мое обходное решение заключается в том, чтобы переопределить его и выполнить то, что документация говорит о его внутреннем:
- (NSString *)sectionIndexTitleForSectionName:(NSString *)sectionName
{
NSString *outName;
if ( [sectionName length] )
outName = [[sectionName substringToIndex:1] uppercaseString];
else
outName = [super sectionIndexTitleForSectionName:sectionName];
return outName;
}
Это приведет к ожидаемому результату.
Ответ 3
Просто добавив, что в моем контроллере решена оригинальная проблема для меня
- (NSString *)controller:(NSFetchedResultsController *)controller sectionIndexTitleForSectionName:(NSString *)sectionName {
return sectionName;}
Å, Ä и Ö отображаются правильно в списке
Ответ 4
Когда я сталкиваюсь с подобной ситуацией, первое, что я задаю себе, это "что делает Apple".
В качестве эксперимента я просто добавил "Joe Äpple" в свою iPhone-адресную книгу, и он появляется под равниной А. Я думаю, что это имеет большой смысл.
Поэтому вместо того, чтобы бросать их под Z или Ä, вы должны сделать то же самое. Должен быть какой-то способ получить "базовую" букву символа юникода для группировки.
Ответ 5
Вы можете использовать кодировку UTF-8
const char *cLetter = (const char *)[ tmp cStringUsingEncoding:NSUTF8StringEncoding];
NSString *original = [NSString stringWithCString:cLetter encoding:NSUTF8StringEncoding];
Ответ 6
Вы выполнили мой ответ на этот другой вопрос?
Я делаю несколько тестов (повторное задание объектов) и вижу странное прерывистое поведение. Он определенно сортирует их правильно (с "Å" сразу после "A", но до "Ä" ). В других случаях он помещает символы вне A-Z в конце (после "Z" ), даже если я не сделал ничего особенного.
Кроме того, я заметил, что "Å" правильно рисуется, если вы возвращаете его строчную форму. Вы пытались переопределить sectionIndexTitleForSectionName:
, чтобы сохранить порядок, но изменить рисованный символ?
Ответ 7
Вы когда-нибудь решали эту проблему?
Мне удалось получить индекс заголовка раздела, чтобы он отображался правильно, реализовав sectionIndexTitlesForTableView: чтобы создать собственный массив заголовков разделов:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
NSMutableArray *indexKeys = [NSMutableArray arrayWithCapacity:30];
NSArray *fetchedResults = [fetchedResultsController fetchedObjects];
NSString *currKey = @"DEFAULT";
for (NSManagedObject *managedObject in fetchedResults) {
NSString *indexKey = [managedObject valueForKey:@"indexKey"];
if (![indexKey isEqualToString:currKey]) {
[indexKeys addObject:indexKey];
currKey = indexKey;
}
}
return indexKeys;
}
Здесь indexKey является первой буквой имени.
Однако это создает одну из двух проблем в разделеForSectionIndexTitle: вместо этого:
Если я просто возвращаю индекс для раздела, это теперь несортированный индекс и больше не соответствует порядку сортировки в fetchResultController:
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return index;
}
В качестве альтернативы, если я перейду на вызов fetchedResultsController, он разбивается на заголовки индексов, отличных от US, потому что это уже не странные символы, используемые функцией fetchedResultsController:
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return [fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];
}
Последний код генерирует ошибку следующего вида при навигации к заголовку "Ø":
Завершение приложения из-за неперехваченного исключения "NSInternalInconsistencyException", причина: "Заголовок индекса при 24 не равен" Ø "
Обходной путь для этого заключается в том, чтобы перевести оскорбительные символы обратно в их странные "я":
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
if ([title isEqualToString:@"Æ"]) {
title = @"\u2206";
} else if ([title isEqualToString:@"Ø"]) {
title = @"\u0178";
} else if ([title isEqualToString:@"Å"]) {
title = @"\u2248";
}
return [fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];
}
Вы можете найти значения Unicode в отладчике с действием "Печать описания на консоль".
Однако хорошим решением было бы выяснить, почему это странное кодирование происходит и предотвращает его.