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

Posted

技术标签:

【中文标题】无法将 NSAttributedString.DocumentAttributeKey 类型的值转换为 .DocumentReadingOptionKey【英文标题】:Cannot convert value of type NSAttributedString.DocumentAttributeKey to .DocumentReadingOptionKey 【发布时间】:2017-06-06 12:51:01 【问题描述】:

我在 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”

我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

您需要传递一个可用的 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 的扩展 updated 应该是这样的:

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\">#redcolor:#F00#greencolor:#0F0#bluecolor: #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 的值)。它将尝试与主线程同步,失败, 和超时。从主线程调用它有效(但仍然可以 如果 HTML 包含对外部资源的引用,则超时,这 应不惜一切代价避免)。 HTML 导入机制的意思 用于实现诸如降价之类的东西(即文本样式, 颜色等),不适用于一般的 HTML 导入

【讨论】:

这太棒了。我能够将 API 中的 &amp;#36 转换为 $。虽然它非常冗长。有没有更快捷的方式?谢谢。 试过了。这是一种清洗,因为它只消除了三个错误行catch, print, return,但无论如何你必须在你的财产上使用String(describing:。另外,我应该在使用 API 时进行错误检查。也许 Swift 5 会让我们用一种神奇的方法来做到这一点,比如encodeHTML =P。 是的。功能是一样的。我想说的是,考虑到安全性的权衡,删除catchprintreturn 是微不足道的。他们都工作。虽然很可怕:) 如果我在 25% 的时间调用此命令时得到一个僵尸,你会说我做错了什么?我没有明确地释放任何地方 我们不能添加 HTML 表格吗?例如let htmlTable = "&lt;table&gt; &lt;tr&gt; &lt;th&gt;Name&lt;/th&gt; &lt;th&gt;Favorite Color&lt;/th&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Bob&lt;/td&gt; &lt;td&gt;Yellow&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Michelle&lt;/td&gt; &lt;td&gt;Purple&lt;/td&gt; &lt;/tr&gt; &lt;/table&gt;"【参考方案2】:

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

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

到:

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

【讨论】:

这是解决方案。非常感谢【参考方案3】:

这对我有用:

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

应用程序将崩溃。

【讨论】:

我怎样才能在其中给出 fontSize 和字体?【参考方案4】:

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

【讨论】:

【参考方案5】:

对于 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
        
    

【讨论】:

【参考方案6】:

使用NSAttributedString.DocumentType.html

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

【讨论】:

【参考方案7】:

我使用 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)

【讨论】:

这太麻烦了。 NSAttributedStringKey 的好处是避免那些冗长的初始化。你应该简单地写let textStroke: [NSAttributedStringKey : Any] = [.strokeColor : UIColor.black, .foregroundColor : UIColor.white, .strokeWidth : -6.0] 【参考方案8】:

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.x5.x 相同。

更多详情请阅读苹果NSAttributedStringDocumentType相关文档

【讨论】:

以上是关于无法将 NSAttributedString.DocumentAttributeKey 类型的值转换为 .DocumentReadingOptionKey的主要内容,如果未能解决你的问题,请参考以下文章

无法将 createdAt 和 updatedAt 保存为日期时间值,也无法将后端保存为前端

C# 无法将类型为“System.Byte[]”的对象强制转换为类型“System.Data.DataTable

无法将类型为“System.Collections.Generic.List`1[EPMS.Domain.SingleItem]”的对象强制转换为类型“EPMS

无法将 .json 文件从 CSV 下载到 JSON 转换并且无法将 JSON 转换为 CSV

无法将 ReactiveUI 添加到 NUnit 测试项目

“无法将图像数据写入路径” - Laravel 图像干预