NSAttributedString initWithHTML некорректная кодировка символов?
-[NSMutableAttributedString initWithHTML:documentAttributes:]
, похоже, приводит в действие специальные символы:
NSString *html = @""Hello" World"; // notice the smart quotes
NSData *htmlData = [html dataUsingEncoding:NSUTF8StringEncoding];
NSMutableAttributedString *as = [[NSMutableAttributedString alloc] initWithHTML:htmlData documentAttributes:nil];
NSLog(@"%@", as);
Это печатает “Hello†World
, за которым следуют некоторые команды RTF. В моем приложении я преобразовываю атрибутированную строку в RTF и отображаю ее в NSTextView
, но символы там тоже повреждены.
В соответствии с документацией кодировка по умолчанию - UTF-8, но я попытался быть явным, и результат будет таким же:
NSDictionary *attributes = @{NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]};
NSMutableAttributedString *as = [[NSMutableAttributedString alloc] initWithHTML:htmlData documentAttributes:&attributes];
Ответы
Ответ 1
Используйте [html dataUsingEncoding:NSUnicodeStringEncoding]
при создании NSData и установите соответствующий параметр кодирования при анализе HTML в атрибутной строке:
Документация для NSCharacterEncodingDocumentAttribute
немного запутанна:
NSNumber, содержащий int, указывающий NSStringEncoding
для файл; для чтения и записи текстовых файлов и написания HTML; по умолчанию для обычного текста используется кодировка по умолчанию; по умолчанию для HTML UTF-8.
Итак, код должен быть:
NSString *html = @""Hello" World";
NSData *htmlData = [html dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)};
NSMutableAttributedString *as =
[[NSMutableAttributedString alloc] initWithHTML:htmlData
options: options
documentAttributes:nil];
Ответ 2
Предыдущий ответ здесь работает, но в основном случайно.
Создание NSData
с помощью NSUnicodeStringEncoding
будет работать, потому что эта константа является псевдонимом для NSUTF16StringEncoding
, а UTF-16 довольно легко идентифицировать систему. Проще, чем UTF-8, который, по-видимому, был идентифицирован как какой-либо другой надмножество ASCII (он выглядит как NSWindowsCP1252StringEncoding
в вашем случае, вероятно, потому, что он является одним из немногих кодировок на основе ASCII с сопоставлениями для 0x8_ и 0x9 _).
Этот ответ ошибочен в цитировании документации для NSCharacterEncodingDocumentAttribute
, потому что "атрибуты" - это то, что вы получаете из -initWithHTML
. Вот почему это NSDictionary **
, а не только NSDictionary *
. Вы можете передать указатель на NSDictionary *
, и вы получите ключи, такие как TopMargin/BottomMargin/LeftMargin/RightMargin, PaperSize, DocumentType, UTI и т.д. Любые значения, которые вы пытаетесь пройти через словарь атрибутов, игнорируются.
Вам нужно использовать "параметры" для передачи значений, а соответствующий ключ опции NSTextEncodingNameDocumentOption
, который не имеет документального значения по умолчанию. Он передает байты в WebKit для синтаксического анализа, поэтому, если вы не укажете кодировку, предположительно, вы получаете эвристику, кодирующую кодировку WebKit.
Чтобы гарантировать соответствие типов кодирования между вашими NSData
и NSAttributedString
, вы должны сделать что-то вроде:
NSString *html = @""Hello" World";
NSData *htmlData = [html dataUsingEncoding:NSUTF8StringEncoding];
NSMutableAttributedString *as =
[[NSMutableAttributedString alloc] initWithHTML:htmlData
options:@{NSTextEncodingNameDocumentOption: @"UTF-8"}
documentAttributes:nil];