Вопрос

Я использую экземпляр UIWebView обрабатывать текст и раскрасить его правильно, он дает результат как HTML, а не отображать его в UIWebView Я хочу отобразить его, используя Core Text с А. NSAttributedString.

Я могу создавать и нарисовать NSAttributedString Но я не уверен, как я могу конвертировать и сопоставить HTML в приписанную строку.

Я понимаю, что под Mac OS X NSAttributedString имеет initWithHTML: Метод, но это был добавленный только Mac и недоступен для iOS.

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

Это было полезно?

Решение

В iOS 7, Uikit добавил initWithData:options:documentAttributes:error: метод, который может инициализировать NSAtttributedString Использование HTML, например:

[[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding] 
                                 options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                           NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)} 
                      documentAttributes:nil error:nil];

В SWIFT:

let htmlData = NSString(string: details).data(using: String.Encoding.unicode.rawValue)
let options = [NSAttributedString.DocumentReadingOptionKey.documentType:
        NSAttributedString.DocumentType.html]
let attributedString = try? NSMutableAttributedString(data: htmlData ?? Data(),
                                                          options: options,
                                                          documentAttributes: nil)

Другие советы

Существует прогресс работы Дополнение открытого исходного кода до NSattribedStringStringString Оливером дробником в Github. Он использует NSCanner для HTML Parsing.

Создание NSATTRIBEDSEDSTRING от HTML необходимо сделать на главной ните!

Обновление: Оказывается, что NSattribedString HTML-рендеринга зависит от WebKit под капотом, а также должен быть запущен на главной ните Или это иногда уравновешивает приложение с помощью Sigtrap.

Новый Relic Crash Log:

enter image description here

Ниже обновлен Безопасен в потоке Swift 2 String расширение:

extension String {
    func attributedStringFromHTML(completionBlock:NSAttributedString? ->()) {
        guard let data = dataUsingEncoding(NSUTF8StringEncoding) else {
            print("Unable to decode data from html string: \(self)")
            return completionBlock(nil)
        }

        let options = [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
                   NSCharacterEncodingDocumentAttribute: NSNumber(unsignedInteger:NSUTF8StringEncoding)]

        dispatch_async(dispatch_get_main_queue()) {
            if let attributedString = try? NSAttributedString(data: data, options: options, documentAttributes: nil) {
                completionBlock(attributedString)
            } else {
                print("Unable to create attributed string from html string: \(self)")
                completionBlock(nil)
            }
        }
    }
}

Применение:

let html = "<center>Here is some <b>HTML</b></center>"
html.attributedStringFromHTML { attString in
    self.bodyLabel.attributedText = attString
}

Выход:

enter image description here

Расширение SWIFT инициализатора на NSattribedStringString

Мой наклон должен был добавить это как расширение для NSAttributedString скорее, чем String. Отказ Я попробовал его как статическое расширение и инициализатор. Я предпочитаю инициализатор, который я включен ниже.

Swift 4.

internal convenience init?(html: String) {
    guard let data = html.data(using: String.Encoding.utf16, allowLossyConversion: false) else {
        return nil
    }

    guard let attributedString = try?  NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil) else {
        return nil
    }

    self.init(attributedString: attributedString)
}

Swift 3

extension NSAttributedString {

internal convenience init?(html: String) {
    guard let data = html.data(using: String.Encoding.utf16, allowLossyConversion: false) else {
        return nil
    }

    guard let attributedString = try? NSMutableAttributedString(data: data, options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil) else {
        return nil
    }

    self.init(attributedString: attributedString)
}
}

Пример

let html = "<b>Hello World!</b>"
let attributedString = NSAttributedString(html: html)

Это String Расширение написано в SWIFT для возврата HTML-строки как NSAttributedString.

extension String {
    func htmlAttributedString() -> NSAttributedString? {
        guard let data = self.dataUsingEncoding(NSUTF16StringEncoding, allowLossyConversion: false) else { return nil }
        guard let html = try? NSMutableAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) else { return nil }
        return html
    }
}

Использовать,

label.attributedText = "<b>Hello</b> \u{2022} babe".htmlAttributedString()

В приведенном выше я намеренно добавил Unicode U2022, чтобы показать, что он правильно отображает Unicode.

Тривиальный: кодировка по умолчанию, которое NSAttributedString использует это NSUTF16StringEncoding (не UTF8!).

SWIFT 3.0 XCODE 8 версия

func htmlAttributedString() -> NSAttributedString? {
    guard let data = self.data(using: String.Encoding.utf16, allowLossyConversion: false) else { return nil }
    guard let html = try? NSMutableAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) else { return nil }
    return html
}

Swift 4.


  • NSATTRIBEDSTRING Удобство инициализатора
  • Без дополнительных охранников
  • бросает ошибку

extension NSAttributedString {

    convenience init(htmlString html: String) throws {
        try self.init(data: Data(html.utf8), options: [
            .documentType: NSAttributedString.DocumentType.html,
            .characterEncoding: String.Encoding.utf8.rawValue
        ], documentAttributes: nil)
    }

}

Применение

UILabel.attributedText = try? NSAttributedString(htmlString: "<strong>Hello</strong> World!")

Единственное решение, которое вы имеете прямо сейчас, это разбирать HTML, создать несколько узлов с данными атрибутами точек / и т. Д., а затем объединить их вместе в NSattribedString. Это много работы, но если сделано правильно, можно многоразоваться в будущем.

Сделал некоторую модификацию на АндрейРаствор и обновление кода для Swift 3:

Этот код теперь использует UITExtView как self и в состоянии наследовать свой исходный шрифт, размер шрифта и цвета текста

Примечание: toHexString() это расширение из здесь

extension UITextView {
    func setAttributedStringFromHTML(_ htmlCode: String, completionBlock: @escaping (NSAttributedString?) ->()) {
        let inputText = "\(htmlCode)<style>body { font-family: '\((self.font?.fontName)!)'; font-size:\((self.font?.pointSize)!)px; color: \((self.textColor)!.toHexString()); }</style>"

        guard let data = inputText.data(using: String.Encoding.utf16) else {
            print("Unable to decode data from html string: \(self)")
            return completionBlock(nil)
        }

        DispatchQueue.main.async {
            if let attributedString = try? NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) {
                self.attributedText = attributedString
                completionBlock(attributedString)
            } else {
                print("Unable to create attributed string from html string: \(self)")
                completionBlock(nil)
            }
        }
    }
}

Пример использования:

mainTextView.setAttributedStringFromHTML("<i>Hello world!</i>") { _ in }

Вышеуказанное решение правильное.

[[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding] 
                                 options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                           NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)} 
                      documentAttributes:nil error:nil];

Но приложение Wioll Crash, если вы работаете на iOS 8.1,2 или 3.

Чтобы избежать аварии, что вы можете сделать: запустите это в очереди. Так что это всегда на главной ните.

Использование NSHTMLTextDocumentType является медленным и трудно контролировать стили. Я предлагаю вам попробовать мою библиотеку, которая называется Atributika. Он имеет свой очень быстрый анализатор HTML. Также вы можете иметь какие-либо имена тегов и определить любой стиль для них.

Пример:

let str = "<strong>Hello</strong> World!".style(tags:
    Style("strong").font(.boldSystemFont(ofSize: 15))).attributedString

label.attributedText = str

Вы можете найти это здесь https://github.com/psharanda/atatributika.

Swift 3:
Попробуй это:

extension String {
    func htmlAttributedString() -> NSAttributedString? {
        guard let data = self.data(using: String.Encoding.utf16, allowLossyConversion: false) else { return nil }
        guard let html = try? NSMutableAttributedString(
            data: data,
            options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
            documentAttributes: nil) else { return nil }
        return html
    }
}  

И для использования:

let str = "<h1>Hello bro</h1><h2>Come On</h2><h3>Go sis</h3><ul><li>ME 1</li><li>ME 2</li></ul> <p>It is me bro , remember please</p>"

self.contentLabel.attributedText = str.htmlAttributedString()

Полезные расширения

Вдохновленный этой нитью, POD и приведением Objc objc Pod и ERICIA SADUN в Cookbook ios Gourmet P.80, я написал расширение на String и дальше NSAttributedString Чтобы отправиться взад и вперед между HTML-струнами и NSattribedStrings и наоборот - на GitHub здесь, который я нашел полезным.

То подписи (опять же, полный код в гисте, ссылка выше):

extension NSAttributedString {
    func encodedString(ext: DocEXT) -> String?
    static func fromEncodedString(_ eString: String, ext: DocEXT) -> NSAttributedString? 
    static func fromHTML(_ html: String) -> NSAttributedString? // same as above, where ext = .html
}

extension String {
    func attributedString(ext: DocEXT) -> NSAttributedString?
}

enum DocEXT: String { case rtfd, rtf, htm, html, txt }

с шрифтом

extension NSAttributedString
{
internal convenience init?(html: String, font: UIFont? = nil) {
    guard let data = html.data(using: String.Encoding.utf16, allowLossyConversion: false) else {
        return nil
    }
    assert(Thread.isMainThread)
    guard let attributedString = try?  NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil) else {
        return nil
    }
    let mutable = NSMutableAttributedString(attributedString: attributedString)
    if let font = font {
        mutable.addAttribute(.font, value: font, range: NSRange(location: 0, length: mutable.length))
    }
    self.init(attributedString: mutable)
}
}

В качестве альтернативы вы можете использовать версии, которые это было получено из и установить шрифт на UILabel после настройки атрибутыStringString

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top