Cannot convert value of type NSAttributedString.Do

2019-01-18 01:28发布

问题:

I found this string extension somewhere on SO that allows me to turn html code into an attributed string:

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

It worked fine in Swift 3, but with Swift 4, Xcode complains:

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

How do I fix this?

回答1:

You need to pass one of the available NSAttributedString DocumentType options:


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

In this case you will need to pass the first one (html) NSAttributedString.DocumentType.html

So the extension updated to Swift 4 should look like this:

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

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



回答2:

Had this after automatic conversion to Swift 4. Was fixed by changing from:

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

to:

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


回答3:

This works for me:

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

If you don’t add

.characterEncoding: String.Encoding.utf8.rawValue

the app will crash.



回答4:

For HTML string, NSAttributedString.DocumentType.html is the correct option.

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


回答5:

swift 4 : i dont know why but all answer have compiler error for me. so i use this extention:

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 ?? ""
    }
}

how to use ?

mylable.text = htmlVariable.html2String



回答6:

I use NSAttributedStringKey and had similar error "Cannot convert value of type" on Swift 4. In case anyone using NSAttributedStringKey comes here looking for an answer, this is how I fixed:

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,]

And this is how I add the attribute to the text:

myLabel.attributedText = NSAttributedString(string: myString, attributes: TextStroke)


回答7:

Use NSAttributedString.DocumentType.html

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