2010-01-30 3 views
12

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

Я следил за этим вопросом для его создания - How to use the first character as a section name, но мой список также содержит элементы, начинающиеся с символов вне A-Z, особенно Å, Ä и Ö, используемые здесь, в Швеции.

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

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

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

кто-то понял это один из?

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

+0

См. Мой ответ на аналогичный вопрос [здесь] (http://stackoverflow.com/a/13292767/616764), в котором я описываю, как создавать локализованные индексы sectionKey. –

ответ

3

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

В качестве эксперимента я просто добавил «Joe Äpple» в свою адресную книгу iPhone, и он появляется под равниной А. Я думаю, это имеет большой смысл.

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

+0

+1 Хорошая точка. Я тоже тестировал некоторые из них, и на самом деле это происходит по-разному в зависимости от выбранного языка в настройках. Подумайте, что сейчас выяснилось, что сортировка понятна. Но все же я не могу заставить его правильно рисовать ... – epatel

1

Вы следили за моим answer другим вопросом?

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

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

+0

+1 Да, основываясь на моем решении ваших рекомендаций, спасибо! Я стараюсь как можно больше доверять основным данным. Посмотрите на подкласс NSFetchedResultsController, первая попытка не удалась – epatel

+0

Это не подкласс, это метод, который вы можете реализовать в своем делегате представления таблиц. – gerry3

+0

Думал, что это был метод (sectionIndexTitleForSectionName :) на контроллере при чтении документов ?! – epatel

15

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

Что нужно делать в этом случае называется «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]; 
} 

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

+1

+1 для исследования и интереса. Но я думаю, что сейчас прикрепил сортировку. Я использую 'localizedCaseInsensitiveCompare:' для дескриптора сортировки для получаемого результирующего контроллера, который будет поддерживать порядок в качестве языкового параметра на устройстве. Но названия индексов и т. Д. Обрабатываются CoreData как gerry3, описанные здесь http://stackoverflow.com/questions/1741093/how-to-use-the-first-character-as-a-section-name/1741131#1741131 – epatel

+0

Это к сожалению, не работает с * Æ * письмом – Shmidt

1

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

Я был в состоянии получить индекс заголовка раздела, чтобы правильно отобразить путем реализации 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]; 
} 

Последний код генерирует ошибку следующего вида при навигации к «O» индекс названию:

Согласующему приложение из-за неперехваченное исключение «NSInternalInconsistencyException», причина: «Индекс заголовок в 24 не равно к «O»»

обойти это перевести символы обижая назад к их странным самостей:

- (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 в отладчике с действием «Print Description to Console».

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

+0

Придется попробовать ... – epatel

4

Я испытываю ту же проблему, о которой сообщалось в исходном вопросе, то есть расширенные символы (за пределами 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; 
} 

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

+0

Звучит многообещающе. Придется попробовать ... если я смогу снова найти файлы проекта;) – epatel

+1

Это было очень хорошее преимущество, однако этого недостаточно для более сложных наборов символов, таких как тайский. В этом случае вы должны использовать '[[sectionName substringWithRange: [sectionName rangeOfComposedCharacterSequenceAtIndex: 0]] uppercaseString];' – FelixLam

+0

Я могу подтвердить, что это сработало хорошо. Должна быть ошибка. –

4

Просто добавить это в мой контроллер решить исходную задачу для меня

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

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

+1

Смотрите мой комментарий выше 'substringToIndex: 1' не работает для символов UTF. Используйте это вместо: '[[sectionName substringWithRange: [sectionName rangeOfComposedCharacterSequenceAtIndex: 0]] uppercaseString];' – FelixLam

+0

Работает для меня? NSString * s = @ "ÉÎØÜ"; \t NSLog (@ "% @", [s substringToIndex: 1]); \t NSLog (@ "% @", [[s substringWithRange: [s rangeOfComposedCharacterSequenceAtIndex: 0]] uppercaseString]); 2014-08-19 15: 01: 15,054 теста [53092: 3703902] Э. 2014-08-19 15: 01: 15,055 тест [53092: 3703902] Э. Если нет другого персонажа, который потерпит неудачу здесь ... – codepoet

2

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

const char *cLetter = (const char *)[ tmp cStringUsingEncoding:NSUTF8StringEncoding]; 
NSString *original = [NSString stringWithCString:cLetter encoding:NSUTF8StringEncoding];