2013-04-11 38 views
16

-[NSMutableAttributedString initWithHTML:documentAttributes:] dường như mangle ký tự đặc biệt:NSAttributedString initWithHTML mã hóa ký tự không chính xác?

NSString *html = @"“Hello” World"; // notice the smart quotes 
NSData *htmlData = [html dataUsingEncoding:NSUTF8StringEncoding]; 
NSMutableAttributedString *as = [[NSMutableAttributedString alloc] initWithHTML:htmlData documentAttributes:nil]; 
NSLog(@"%@", as); 

Đó in “Hello†World tiếp theo một số lệnh RTF. Trong ứng dụng của tôi, tôi chuyển đổi chuỗi được phân bổ thành RTF và hiển thị nó trong một NSTextView, nhưng các ký tự cũng bị hỏng ở đó.

Theo các tài liệu, bảng mã mặc định là UTF-8, nhưng tôi đã cố gắng là rõ ràng và kết quả là như nhau:

NSDictionary *attributes = @{NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]}; 
NSMutableAttributedString *as = [[NSMutableAttributedString alloc] initWithHTML:htmlData documentAttributes:&attributes]; 

Trả lời

28

Sử dụng [html dataUsingEncoding:NSUnicodeStringEncoding] khi tạo NSData và thiết lập các tùy chọn mã hóa phù hợp khi bạn phân tích cú pháp HTML vào một chuỗi do:

các tài liệu cho NSCharacterEncodingDocumentAttribute là hơi khó hiểu:

NSNumber, có chứa một int chỉ định NSStringEncoding cho tệp ; để đọc và viết các tệp văn bản thuần tuý và viết HTML; mặc định cho văn bản thuần là mã hóa mặc định; mặc định cho HTML là UTF-8.

Vì vậy, bạn mã nên là:

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]; 
+0

vĩ đại. Cám ơn vì cái này. (y) – Sid

+0

Bạn nên thử câu trả lời khác trước tiên trong trường hợp họ đúng về câu trả lời của tôi chỉ làm việc vô tình. Tôi đã không có cơ hội để tự mình thử nghiệm nó. : -X – alltom

+0

Chúng có một phần đúng. Đây là câu trả lời tương tự (nhiều hơn hoặc ít hơn) và nó hoạt động.Tôi đã làm cho câu trả lời này rõ ràng hơn vì nó được đánh dấu là chính xác. –

10

Câu trả lời trước đây hoạt động, nhưng chủ yếu là do tình cờ.

Tạo NSData với NSUnicodeStringEncoding sẽ có xu hướng hoạt động, bởi vì hằng số đó là bí danh cho NSUTF16StringEncoding và UTF-16 khá dễ dàng để hệ thống nhận dạng. Dễ dàng hơn UTF-8, mà dường như đã được xác định là một số superset khác của ASCII (có vẻ như NSWindowsCP1252StringEncoding trong trường hợp của bạn, có lẽ vì nó là một trong số ít mã ASCII dựa trên ánh xạ cho 0x8_ và 0x9_).

Câu trả lời đó bị nhầm lẫn khi trích dẫn tài liệu cho NSCharacterEncodingDocumentAttribute, vì "thuộc tính" là những gì bạn nhận được trong số của -initWithHTML. Đó là lý do tại sao nó là NSDictionary ** và không chỉ NSDictionary *. Bạn có thể chuyển con trỏ đến số NSDictionary * và bạn sẽ nhận được các khóa như TopMargin/BottomMargin/LeftMargin/RightMargin, PaperSize, DocumentType, UTI, v.v. Bất kỳ giá trị nào bạn cố gắng vượt qua trong thông qua từ điển "thuộc tính" làm ngơ.

Bạn cần sử dụng "tùy chọn" để chuyển các giá trị trong và khóa tùy chọn có liên quan là NSTextEncodingNameDocumentOption, không có giá trị mặc định được ghi lại. Nó chuyển các byte sang WebKit để phân tích cú pháp, vì vậy nếu bạn không chỉ định mã hóa, có lẽ bạn đang nhận được chẩn đoán đoán mã hóa của WebKit.

Để đảm bảo sự phù hợp với các loại mã hóa giữa NSData của bạn và NSAttributedString, những gì bạn cần làm là một cái gì đó như:

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

NSMutableAttributedString *as = 
    [[NSMutableAttributedString alloc] initWithHTML:htmlData 
              options:@{NSTextEncodingNameDocumentOption: @"UTF-8"} 
           documentAttributes:nil]; 
+0

Tôi sẽ cố gắng này, cảm ơn bạn! – alltom

+0

Tôi không nghĩ đó là câu trả lời khác. Nó không hoàn thành. –

+0

Thực ra, đây là câu trả lời đúng. Câu trả lời khác thực sự chỉ hoạt động nếu '-initWithHTML' bằng cách phát hiện đúng mã hóa. Sử dụng 'tùy chọn' là đúng cách để đi. Cảm ơn! – fbitterlich

Các vấn đề liên quan