NSAttributedString initWithHTML字符编码不正确?

all*_*tom 18 cocoa nsattributedstring

-[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);
Run Code Online (Sandbox Code Playgroud)

打印“Hello†World后跟一些RTF命令.在我的应用程序中,我将属性字符串转换为RTF并将其显示在一个NSTextView,但字符也在那里被破坏.

根据文档,默认编码是UTF-8,但我尝试显式,结果是相同的:

NSDictionary *attributes = @{NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]};
NSMutableAttributedString *as = [[NSMutableAttributedString alloc] initWithHTML:htmlData documentAttributes:&attributes];
Run Code Online (Sandbox Code Playgroud)

all*_*tom 31

[html dataUsingEncoding:NSUnicodeStringEncoding]在将HTML解析为属性字符串时,在创建NSData时使用并设置匹配的编码选项:

文档NSCharacterEncodingDocumentAttribute略有混淆:

NSNumber,包含指定NSStringEncoding文件的int ; 用于读写纯文本文件和编写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];
Run Code Online (Sandbox Code Playgroud)


小智 10

之前的答案在这里有效,但主要是偶然的.

使用NSDatawith NSUnicodeStringEncoding将会起作用,因为该常量是别名NSUTF16StringEncoding,并且UTF-16很容易被系统识别.比UTF-8更容易,UTF-8显然被认为是ASCII的其他超集(看起来NSWindowsCP1252StringEncoding在你的情况下,可能是因为它是为数不多的基于ASCII的编码之一,其映射为0x8_和0x9_).

这个问题的答案是引用的文件误NSCharacterEncodingDocumentAttribute,因为"属性"是你得到了什么出来-initWithHTML.这就是为什么它NSDictionary **不仅仅是NSDictionary *.您可以在一个指针传递给NSDictionary *,你会得到出像TOPMARGIN/BottomMargin/LEFTMARGIN/RightMargin,纸张大小,DocumentType,尿路感染等,试图传递任何值的键通过"属性"字典被忽略.

你需要使用"选项"值传递,而相关的选项键是NSTextEncodingNameDocumentOption,它没有记录默认值.它将字节传递给WebKit进行解析,因此如果您没有指定编码,可能是您正在获取WebKit的编码猜测启发式算法.

为了保证您NSDataNSAttributedString您之间的编码类型匹配,您应该做的是:

NSString *html = @"“Hello” World";
NSData *htmlData = [html dataUsingEncoding:NSUTF8StringEncoding];

NSMutableAttributedString *as =
    [[NSMutableAttributedString alloc] initWithHTML:htmlData
                                            options:@{NSTextEncodingNameDocumentOption: @"UTF-8"}
                                 documentAttributes:nil];
Run Code Online (Sandbox Code Playgroud)


mat*_*ema 8

接受答案的 Swift 版本是:

let htmlString: String = "Hello world contains html</br>"
let data: Data = Data(htmlString.utf8)

let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
    .documentType: NSAttributedString.DocumentType.html,
    .characterEncoding: String.Encoding.utf8.rawValue
]

let attributedString = try? NSAttributedString(data: data,
    options: options,
    documentAttributes: nil)
Run Code Online (Sandbox Code Playgroud)