Cannot Convert Value of Type Nsattributedstring.Documentattributekey to .Documentreadingoptionkey

Cannot convert value of type NSAttributedString.DocumentAttributeKey to .DocumentReadingOptionKey

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

}
}

Playground Testing

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

Cannot convert value of type 'NSAttributedString.DocumentAttributeKey' , DocumentReadingOptionKey also not working

The value you are trying to pass to the options parameter needs to be split up.

First, the documentType is from NSAttributedString.DocumentReadingOptionKey, not NSAttributedString.DocumentAttributeKey.

Seconds, the kern needs to be passed to the documentAttributes parameter, not the options parameter.

It's much easier if you split up the code:

let options: [NSAttributedString.DocumentReadingOptionKey : Any] = [ .documentType: NSAttributedString.DocumentType.html ]
let attributes = [ NSAttributedString.Key.kern: 2.0 ] as NSDictionary?
let data = htmlString.data(using: .utf8)!
let attrStr = try? NSAttributedString(data: data, options: options, documentAttributes: &attributes)

How to convert [String : Any] to [NSAttributedStringKey : Any]

NSAttributedStringKey has an initialiser that takes a String, and you can use Dictionary's init(uniqueKeysWithValues:) initialiser in order to build a dictionary from a sequence of key-value tuples where each key is unique (such as is the case here).

We just have to apply a transform to attr that converts each String key into an NSAttributedStringKey prior to calling Dictionary's initialiser.

For example:

let attributes: [String : Any]? = // ...

let attributedString = NSMutableAttributedString(string: "hello world")
let range = NSRange(location: 0, length: attributedString.string.utf16.count)

if let attributes = attributes {
let convertedAttributes = Dictionary(uniqueKeysWithValues:
attributes.lazy.map { (NSAttributedStringKey($0.key), $0.value) }
)
attributedString.addAttributes(convertedAttributes, range: range)
}

We're using lazy here to avoid the creation of an unnecessary intermediate array.

cannot convert value of type 'OSLogMessage' to expected dictionary key type 'AnyHashable'

I solved this one for anyone who comes across this. Code below fixed all problems

@State var selection = ""
VStack {
ForEach(viewModel.items.indices, id: \.self) { i in
HStack {
Text(viewModel.items[i].name)
Spacer()
Button(action: {
self.selection = viewModel.items[i].name
self.addItems()
}) {
Text("Add")
}
}
}
}
.onAppear() { self.viewModel.fetchData() }
func addItems() {
let db = Firestore.firestore()
db.collection("movies").document("\(self.movie.id)").updateData([AnyHashable("items"): FieldValue.arrayUnion(["\(self.selection)"])])
}


Related Topics



Leave a reply



Submit