Не американские символы в заголовках разделов для UITableView - PullRequest
13 голосов
/ 30 января 2010

Я добавил список разделов для простого приложения Core Data для iPhone.

Я следовал за этим вопросом, чтобы создать его - Как использовать первый символ в качестве имени раздела , но мой список также содержит элементы, начинающиеся с символов вне AZ, особенно Å, Ä и Ö, используемые здесь в Швеции .

Проблема сейчас в том, что когда в табличном представлении отображается список разделов, последние три символа отображаются неправильно. Смотрите изображение ниже

Похоже, сейчас мой лучший вариант - сортировать эти элементы по 'Z'

if ([letter isEqual:@"Å"] ||
    [letter isEqual:@"Ä"] ||
    [letter isEqual:@"Ö"]) 
    letter = @"Z";

Кто-то, кто понял это?

И пока я на этом ... «Å», «Ä» и «Ö» должны быть отсортированы в этом порядке, но отсортированы как «Ä», «Å» и «Ö» по основным данным NSSortDescriptor. Я попытался установить селектор на localizedCaseInsensitiveCompare:, но это дает ошибку out of order section name 'Ä. Objects must be sorted by section name'. Видели это тоже?

Ответы [ 7 ]

15 голосов
/ 31 января 2010

Так что я не мог отпустить этого и нашел следующее:

То, что вам нужно сделать в этом случае, называется «Форма нормализации Unicode 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];
}

(Я нашел этот код в списке рассылки, забыл источник, но я взял его и немного исправил)

4 голосов
/ 22 августа 2010

Просто добавив это в мой контроллер, я решил оригинальную проблему

- (NSString *)controller:(NSFetchedResultsController *)controller sectionIndexTitleForSectionName:(NSString *)sectionName {
return sectionName;}

Å, Ä и Ö правильно отображаются в списке

4 голосов
/ 30 июня 2010

Я столкнулся с той же проблемой, о которой сообщалось в исходном вопросе, то есть расширенные символы (за пределами страницы Unicode 0) не отображаются должным образом в строке индекса.

Хотя я, кажется, передаю NSFetchedResultsController правильные строки одиночных символов Юникода, в ответ на доступ к свойству sectionIndexTitles я получаю те же символы с старшим байтом, установленным в 0; например, символ \ u30a2 (буква A KATAKANA) становится \ u00a2 (знак зодиака).

Я не уверен, является ли это ошибкой в ​​методе sectionIndexTitleForSectionName: NSFetchedResultsController или моей собственной ошибкой в ​​другом месте, однако мой обходной путь состоит в том, чтобы переопределить его и выполнить то, что в документации сказано, что оно делает внутренне:

- (NSString *)sectionIndexTitleForSectionName:(NSString *)sectionName
{
    NSString    *outName;

    if ( [sectionName length] )
        outName = [[sectionName substringToIndex:1] uppercaseString];
    else
        outName = [super sectionIndexTitleForSectionName:sectionName];

    return outName;
}

Это дает ожидаемый результат.

3 голосов
/ 30 января 2010

Когда я сталкиваюсь с такой ситуацией, первое, что я спрашиваю себя: «Что делает Apple».

В качестве эксперимента я только что добавил «Джо Эппл» в свою адресную книгу iPhone, и он появился под обычным «А». Думаю, в этом есть много смысла.

Так что вместо того, чтобы бросать их под Z или Ä, вы должны сделать то же самое. Должен быть какой-то способ получить «базовую» букву символа юникода для группировки.

2 голосов
/ 08 сентября 2012

Вы можете использовать кодировку UTF-8

const char *cLetter = (const char *)[ tmp cStringUsingEncoding:NSUTF8StringEncoding]; 
NSString *original = [NSString stringWithCString:cLetter encoding:NSUTF8StringEncoding];
1 голос
/ 18 апреля 2010

Вы когда-нибудь решали эту проблему?

Мне удалось добиться правильного отображения индекса заголовка раздела, реализовав 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 - это первая буква имени.

Однако это создает одну из двух проблем в sectionForSectionIndexTitle: вместо этого:

Если я просто возвращаю индекс для раздела, то это теперь несортированный индекс и больше не соответствует порядку сортировки в fetchResultController:

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
    return index;
}

В качестве альтернативы, если я передаю вызов fetchedResultsController, он прерывается на заголовки неамериканских индексов, поскольку они больше не являются странными символами, используемыми 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 можно найти в отладчике с помощью действия «Печать описания в консоль».

Однако хорошим решением было бы выяснить, почему происходит эта странная кодировка, и предотвратить ее.

1 голос
/ 31 января 2010

Следовали ли вы за моим ответом на этот другой вопрос?

Я делаю некоторые тесты (перезагружаю свои объекты) и вижу странное прерывистое поведение. Он определенно сортирует их правильно (с «Å» сразу после «A», но перед «Ä») иногда . В других случаях это ставит символы за пределами A-Z все в конце (после 'Z'), хотя я не делал ничего особенного.

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

...