Изменение длины строки после сохранения в Core Data

Итак, вот проблема.

у меня есть строка

    Белый Клык-0.fb2

Длина метода NSString возвращает 16

После сохранения строки в Core Data (бэкенд — sqlite)

Длина метода NSString возвращает 17, но визуально строка остается прежней

    Белый Клык-0.fb2

И, очевидно, метод isEqualToString: вернуть НЕТ

Потратив много времени на эксперименты, я понял, что проблема в этом письме:

    й

Удаление этой буквы решит проблему.

Но это продолжает сводить меня с ума, почему происходит что-то подобное?

Вот обходной путь, который работает, но меня не удовлетворяет:

  1. stringByReplacingPercentEscapesUsingEncoding: - нужно преобразовать строку сразу в и после запроса БД
  2. транслитерировать всю строку - своего рода хак

И вот обходной путь, который не работает:

  1. строкаWithUTF8String
  2. Преобразование экранированных символов UTF8 вернуться к исходной форме

Пожалуйста, помогите мне понять, что происходит со строкой после сохранения в Core Data.

И есть более элегантное решение, которое я сделал?


person Wert1go    schedule 25.02.2013    source источник
comment
Это может быть проблема, связанная с нормализацией Unicode. Просто попробуйте сравнить строку ваших основных данных с [yourOriginalString decomposedStringWithCanonicalMapping] и посмотреть, работает ли это... (я тестировал его, и он возвращает длину 17 при вызове строки в вашем примере)   -  person Alladinian    schedule 25.02.2013
comment
Спасибо! К сожалению, это действительно работает, но я даже не слышал о каноническом отображении. Можете ли вы добавить ответ? Отмечаю как правильный ответ.   -  person Wert1go    schedule 25.02.2013
comment
Если вам действительно нужно сохранить исходную строку, включая составные символы, вы должны сохранить ее как NSData: [myString dataUsingEncoding:NSUTF16StringEncoding]   -  person Nikolai Ruhe    schedule 25.02.2013


Ответы (1)


Проблема может быть связана с нормализацией Unicode. Таким образом, кажется, что Coredata хранит строку в разложенном виде (поэтому й считается за 2 - один для буквы и один для акцента), и поэтому вы получаете разницу в длине. Если вы попытаетесь разложить исходную строку, прежде чем сравнивать ее с тем, что возвращает Coredata, она должна работать:

[yourOriginalString decomposedStringWithCanonicalMapping]

Теперь, причина этого выходит за рамки моей области знаний. Я постоянно использую coredata для управления своими моделями и несколько раз работал с греческими/русскими строками, и у меня никогда не было такой проблемы. Если кто-то может расширить это и пролить свет, я также был бы очень заинтересован в этой теме.

person Alladinian    schedule 25.02.2013
comment
Базы данных обычно выполняют такого рода каноническую декомпозицию для повышения производительности сортировки и поиска. Когда база данных знает, что внутреннее представление всегда декомпозировано, проверка на равенство — это просто побитовое сравнение. - person Nikolai Ruhe; 25.02.2013
comment
@NikolaiRuhe Это имеет смысл, но разве методы сравнения NSString не должны обрабатывать это автоматически? - person Alladinian; 25.02.2013
comment
Да, но прирост производительности достигается там, где еще нет строк NSString: внутренняя сортировка, индексация и поиск в базе данных требуют быстрого сравнения строк. Повышенная производительность является результатом осознания того, что вам не нужен более сложный алгоритм, учитывающий составные символы. - person Nikolai Ruhe; 25.02.2013
comment
@NikolaiRuhe Да, действительно, это произошло бы в случае запроса к базе данных (хотя, вообще говоря, хранилище основных данных также может быть XML-файлом), но проблема здесь в том, что объект, извлекаемый из хранилища (NSString в этот пример) не сравнивается, как ожидалось, с другим NSString. Кстати спасибо за инфу! - person Alladinian; 25.02.2013
comment
А, теперь я понимаю. Вы имели в виду, что isEqual: NSString должен прозрачно обрабатывать композиции символов? Ну, это не так. Композиция/декомпозиция символов — распространенный источник ошибок или, по крайней мере, путаницы, которую не может решить никто, кроме прикладного инженера. По крайней мере, реализация Cocoa isEqual: соответствует большинству фреймворков Unicode. Если вам нужна автоматическая декомпозиция, вы можете использовать compare:. - person Nikolai Ruhe; 25.02.2013
comment
@Alladinian Для нескольких путей я получаю предварительно составленную строку. Путь содержит Ü. Любая подсказка? - person Parag Bafna; 17.04.2018