无法将类型 NSAttributedString.DocumentAttributeKey 的值转换为 .DocumentReadingOptionKey

Cannot convert value of type NSAttributedString.DocumentAttributeKey to .DocumentReadingOptionKey

我在 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 抱怨:

Cannot convert value of type 'NSAttributedString.DocumentAttributeKey' to expected dictionary key type 'NSAttributedString.DocumentReadingOptionKey'

我该如何解决这个问题?

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


Hypertext Markup Language (HTML) document.

static let html: NSAttributedString.DocumentType

Plain text document.

static let plain: NSAttributedString.DocumentType

Rich text format document.

static let rtf: NSAttributedString.DocumentType

Rich text format with attachments document.

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

Discussion The HTML importer should not be called from a background thread (that is, the options dictionary includes documentType with a value of html). It will try to synchronize with the main thread, fail, and time out. Calling it from the main thread works (but can still time out if the HTML contains references to external resources, which should be avoided at all costs). The HTML import mechanism is meant for implementing something like markdown (that is, text styles, colors, and so on), not for general HTML import

这对我有用:

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.rawValue

应用程序将崩溃。

我使用 NSAttributedStringKey 并且在 Swift 上有类似的错误 "Cannot convert value of type" 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)

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

Swift 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
        }
    }
}

在自动转换为 Swift 后有这个 4. 通过更改以下内容来修复:

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

至:

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

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

使用NSAttributedString.DocumentType.html

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

Swift 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 文档