我正在使用一个实例 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];

在斯威夫特中:

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)

其他提示

有一个工作在进展开源除了NSAttributedString 通过奥利弗Drobnik在Github上。它使用用于NSScanner HTML解析。

创建与HTML的NSAttributedString必须在主线程上完成!

更新:原来,NSAttributedString HTML渲染依赖WebKit的引擎盖下,和必须在主线程上运行 也偶尔会崩溃的应用程序有一个SIGTRAP

新遗物崩溃日志:

下面是一个更新的线程安全夫特2字符串延伸:

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
}

输出:

夫特初始化扩展上NSAttributedString

我的倾向是添加此作为一个扩展到NSAttributedString而非String。我想它作为一个静态的扩展和初始化。我更喜欢初始化这是我在下面列出。

<强>夫特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)
}

<强>夫特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返回一个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)

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
}

雨燕4


  • NSAttributedString 便捷初始化器
  • 无需额外看守
  • 抛出错误

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,建立与给定的点/字体/等属性一些节点,然后将它们结合在一起成一个NSAttributedString。这是一个大量的工作,但如果做得正确,可以在未来可重复使用的。

提出了一些修改上安德鲁的溶液和代码更新到夫特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];

但是,如果你在iOS 8.1,2或3运行它的应用程序wioll崩溃。

为避免你所能做的就是崩溃:在队列中运行此。因此,它总是在主线程。

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/Atributika

<强>夫特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()

与字体

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 attributedString

scroll top