39

我在 SO 的某处发现了这个字符串扩展,它允许我将 html 代码转换为属性字符串:

func html2AttributedString() -> NSAttributedString {
    return try! NSAttributedString(data: self.data(using: String.Encoding.unicode, allowLossyConversion: true)!, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil)
}

它在 Swift 3 中运行良好,但在 Swift 4 中,Xcode 抱怨:

无法将类型“NSAttributedString.DocumentAttributeKey”的值转换为预期的字典键类型“NSAttributedString.DocumentReadingOptionKey”

我该如何解决?

4

8 回答 8

92

您需要传递可用的 NSAttributedString DocumentType选项之一:


超文本标记语言 (HTML) 文档。

static let html: NSAttributedString.DocumentType

纯文本文档。

static let plain: NSAttributedString.DocumentType

富文本格式文档。

static let rtf: NSAttributedString.DocumentType

带有附件文档的富文本格式。

static let rtfd: NSAttributedString.DocumentType

在这种情况下,您需要传递第一个(html) NSAttributedString.DocumentType.html

所以更新到 Swift 4 的扩展应该是这样的:

extension NSAttributedString {
    convenience init(data: Data, documentType: DocumentType, encoding: String.Encoding = .utf8) throws {
        try self.init(data: data,
                      options: [.documentType: documentType,
                                .characterEncoding: encoding.rawValue],
                      documentAttributes: nil)
    }
    convenience init(html data: Data) throws {
        try self.init(data: data, documentType: .html)
    }
    convenience init(txt data: Data) throws {
        try self.init(data: data, documentType: .plain)
    }
    convenience init(rtf data: Data) throws {
        try self.init(data: data, documentType: .rtf)
    }
    convenience init(rtfd data: Data) throws {
        try self.init(data: data, documentType: .rtfd)
    }
}

extension StringProtocol {
    var data: Data { return Data(utf8) }
    var htmlToAttributedString: NSAttributedString? {
        do {
            return try .init(html: data)
        } catch {
            print("html error:", error)
            return nil
        }
    }
    var htmlDataToString: String? {
        return htmlToAttributedString?.string
    }
}

extension Data {
    var htmlToAttributedString: NSAttributedString? {
        do {
            return try .init(html: self)
        } catch {
            print("html error:", error)
            return nil
        }

    }
}

游乐场测试

let htmlString = "<style type=\"text/css\">#red{color:#F00}#green{color:#0F0}#blue{color: #00F; font-weight: Bold; font-size: 32}</style><span id=\"red\" >Red</span><span id=\"green\" > Green </span><span id=\"blue\">Blue</span>"

let htmlData = Data(htmlString.utf8)

htmlString.htmlToAttributedString
htmlData.htmlToAttributedString

讨论不应从后台线程调用 HTML 导入器(即选项字典包含值为 html 的 documentType)。它将尝试与主线程同步,失败并超时。从主线程调用它是可行的(但如果 HTML 包含对外部资源的引用,仍然会超时,应该不惜一切代价避免这种情况)。HTML 导入机制是为了实现诸如 markdown 之类的东西(即文本样式、颜色等),而不是用于一般的 HTML 导入

于 2017-06-06T13:40:31.843 回答
23

在自动转换为 Swift 4 后出现此问题。已通过以下更改修复:

NSMutableAttributedString(data: data, 
   options: [NSAttributedString.DocumentAttributeKey.documentType : NSAttributedString.DocumentType.html], 
   documentAttributes: nil)

到:

NSMutableAttributedString(data: data,
   options: [.documentType : NSAttributedString.DocumentType.html],
   documentAttributes: nil) {
于 2017-09-21T11:42:53.403 回答
14

这对我有用:

let attrStr = try! NSAttributedString(
    data: modifiedFont.data(using: .unicode, allowLossyConversion: true)!,
    options:[.documentType: NSAttributedString.DocumentType.html,
    .characterEncoding: String.Encoding.utf8.rawValue],
    documentAttributes: nil)

如果不添加

.characterEncoding:String.Encoding.utf8。原始值

该应用程序将崩溃。

于 2017-09-08T04:19:40.340 回答
7

swift 4:我不知道为什么所有答案对我来说都有编译器错误。所以使用这个扩展:

extension String {
    var html2AttributedString: NSAttributedString? {
        do {
            return try NSAttributedString(data: data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue))!,
                                          options: [.documentType: NSAttributedString.DocumentType.html,
                                                    .characterEncoding: String.Encoding.utf8.rawValue],
                                          documentAttributes: nil)
        } catch {
            print("error: ", error)
            return nil
        }
    }
    var html2String: String {
        return html2AttributedString?.string ?? ""
    }
}

如何使用 ?

mylable.text = htmlVariable.html2String

于 2018-02-03T15:18:01.863 回答
4

对于 HTML 字符串,NSAttributedString.DocumentType.html是正确的选项。

斯威夫特 4

extension String {

    var utfData: Data? {
        return self.data(using: .utf8)
    }

    var htmlAttributedString: NSAttributedString? {
        guard let data = self.utfData else {
            return nil
        }
        do {
            return try NSAttributedString(data: data,
           options: [
                     NSAttributedString.documentType: NSAttributedString.DocumentType.html,
                     NSAttributedString.characterEncoding: String.Encoding.utf8.rawValue
                    ], documentAttributes: nil)
        } catch {
            print(error.localizedDescription)
            return nil
        }
    }
}
于 2017-09-16T17:57:17.053 回答
1

采用NSAttributedString.DocumentType.html

NSMutableAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html] , documentAttributes: nil)
于 2018-10-29T12:37:59.240 回答
0

我使用 NSAttributedStringKey 并且在 Swift 4 上出现了类似的错误“无法转换类型的值”。如果有人使用 NSAttributedStringKey 来这里寻找答案,这就是我修复的方法:

let TextStroke: [NSAttributedStringKey : Any] = [
    NSAttributedStringKey(rawValue: NSAttributedStringKey.strokeColor.rawValue) : UIColor.black,
    NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue) : UIColor.white,
    NSAttributedStringKey(rawValue: NSAttributedStringKey.strokeWidth.rawValue) : -6.0,]

这就是我将属性添加到文本的方式:

myLabel.attributedText = NSAttributedString(string: myString, attributes: TextStroke)
于 2017-09-14T18:33:07.660 回答
0

斯威夫特 4.x & 5.x

if let rtfPath = Bundle.main.url(forResource: "FileName", withExtension: "rtf") {
        do {
            let attributedString: NSAttributedString = try NSAttributedString(url: rtfPath, options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.rtf], documentAttributes: nil)
            debugPrint(attributedString)
        } catch {
            print("Error while reading the file - \(error.localizedDescription)")
        }
 }

从文件中获取 NSAttributedString 将在Swift 3.x中进行更改,如下所示:

let attributedStringWithRtf: NSAttributedString = try NSAttributedString(url: rtfPath, options: [NSDocumentTypeDocumentAttribute:NSRTFTextDocumentType], documentAttributes: nil)

所有其他代码与Swift 4.x & 5.x相同。

有关更多详细信息,请阅读与NSAttributedStringDocumentType相关的 Apple 文档

于 2020-11-04T21:13:26.243 回答