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
Customizing the Colors of a Uisegmentedcontrol
How to Reset the Application Data After Each Test with Xcode 7 UI Testing
App Crashes After Executing Background Fetch Completionhandler
Detect Moment When Newline Starts in Uitextview
How to Take Screenshot of Portion of Uiview
Scanning Barcode or Qr Code in Swift 3.0 Using Avfoundation
How to Determine If the Sim/Phone Number Has Changed
Workaround for Rounded Corners of Grouped Uitableview, iOS7
Skspritenode Position in Universal Game
How to Create Custom View Programmatically in Swift Having Controls Text Field, Button etc
Where to Place a .Txt File and Read from It in a iOS Project
Embedding a Framework Within a Framework (iOS 8+)
Can Swift Closures Be Set to a Default Value When Used as a Parameter in a Function
Core Location Not Working in iOS 8