Подтвердить что ты не робот

Неамериканские символы в заголовках разделов для 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'. Видите это тоже?

4b9b3361

Ответ 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 в отладчике с действием "Печать описания на консоль".

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