I'm getting a warning in the debugger in XCode: Incorrect NSStringEncoding value 0x8000100 detected when converting an NSAttributedString to html data. Not sure what is causing this or how to fix it. Here is my code:
let testString = NSAttributedString(string: "test")
let documentAttributes: [NSAttributedString.DocumentAttributeKey: Any] = [.documentType: NSAttributedString.DocumentType.html]
let htmlData = try? testString.data(from: NSRange(location: 0, length: testString.length), documentAttributes: documentAttributes)
The data does get created, but not sure why I'm getting the warning.
I finally figured out what was causing this. It seems that the string to data function wants some idea of what text encoding to use. Here is the fixed code which removes the debugger warning:
let testString = NSAttributedString(string: "test")
let documentAttributes: [NSAttributedString.DocumentAttributeKey: Any] = [.documentType: NSAttributedString.DocumentType.html, .characterEncoding:String.Encoding.utf8.rawValue]
let htmlData = try? testString.data(from: NSRange(location: 0, length: testString.length), documentAttributes: documentAttributes)
I'm using this way and it works fine, but has a slowness fallback because of the usage of NSHTMLTextDocumentType as i did my research
do {
let attributedOptions:[String: Any] = [
NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue]
let date = html.data(using: String.Encoding.utf8, allowLossyConversion: true)!
return try NSAttributedString(data: data, options: attributedOptions , documentAttributes: nil)
} catch let error as NSError {
print("htmo2String \(error)")
}
any ideas how to do it faster or another efficient way to do it!
Maybe you can execute the parse code on a queue...
func parse(_ html: String, completionHandler: #escaping (_ attributedText: NSAttributedString?) -> (Void)) -> Void
{
let htmlData = text.data(using: String.Encoding.utf8, allowLossyConversion: false)
let options: [String: AnyObject] = [
NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType as AnyObject
]
completionHandler(try? NSAttributedString(data: htmlData!, options: options, documentAttributes: nil))
}
And now call the function and wait from response...
let queue: DispatchQueue = DispatchQueue(label: "com.yourcompany.Process./html_converter")
queue.async
{
parse("<p>¡Hola mundo</p>", completionHandler: { (attributtedString: NSAttributedString?) -> (Void) in
if let attributtedString = attributtedString
{
DispatchQueue.main.async
{
print("str:: \(attributtedString)")
}
}
})
}
Did you try o use a UIWebView to present HTML content ?
You can display HTML from a string or from a URL, as you prefer.
Here is an example to display HTML from a string :
string sHTMLContent = "<html><head><body><p>Hello World</p></body></head></html>";
m_WebView.LoadHtmlString(sHTMLContent , null);
Then you can set the size of your Webview to be equal to your textview with constraints. The webview will be scrollable automatically if needed.
Final string extension to show html string efficiently with #Adolfo async idea
with the ability to change font and color ^_^
extension String {
func html2StringAsync(_ fontSize: CGFloat? = nil, color: UIColor? = nil, completionBlock:#escaping (NSAttributedString) ->()) {
let fontSize = fontSize ?? 10
let fontColor = color ?? UIColor.black
let font = "Avenir !important"
let html = "<div style=\"font-family:\(font); font-size:\(fontSize)pt; color:\(fontColor.hexString);\">" + self + "</div>"
if let data = html.data(using: String.Encoding.utf8, allowLossyConversion: true){
DispatchQueue.main.async {
do {
let attributedOptions:[String: Any] = [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue]
let attrStr = try NSAttributedString(data: data, options: attributedOptions , documentAttributes: nil)
completionBlock(attrStr)
} catch let error as NSError {
print("htmo2String \(error)")
}
}
}else{
completionBlock(NSAttributedString(string: self))
}
}
}
I have a String with html content, something like this
let content:String = "<p>p1</p><p>p2</p>"
let contentFromHtml = try! NSAttributedString(
data: content.dataUsingEncoding(NSUnicodeStringEncoding, allowLossyConversion: true)!,
options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
label.text = contentFromHtml
I can't get the "carriage return"
Try label.attributedText
This property expects an attributedString, just like in your example.
I have on WKInterfaceLabel in which i can not load HTML Tag like
<h1>Grishneshwar Jyotirling</h1>
and I can't use NSMutableAttributedString so please help me to finding regarding things.
var htmlText = "<h1>Grishneshwar Jyotirling</h1> Grishneshwar Jyotirling"
let attributeText: NSAttributedString?
if let htmlData = htmlText.dataUsingEncoding(NSUnicodeStringEncoding) {
do {
attributeText = try NSAttributedString(data: htmlData , options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil)
myLabel.setAttributedText(attributeText)
}catch let e as NSError {
print("Couldn't translate \(htmlText): \(e.localizedDescription) ")
}
I would like to display html formatted text on a UILabel in IOS.
In Android, it has api like this .setText(Html.fromHtml(somestring));
Set TextView text from html-formatted string resource in XML
I would like to know what / if there is an equivalent in ios?
I search and find this thread:
How to show HTML text from API on the iPhone?
But it suggests using UIWebView. I need to display html formatted string in each table cell, so I think have 1 webview per row seems a bit heavy.
Is that any other alternative?
Thank you.
Swift 3.0
do {
let attrStr = try NSAttributedString(
data: "<b><i>text</i></b>".data(using: String.Encoding.unicode, allowLossyConversion: true)!,
options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
label.attributedText = attrStr
} catch let error {
}
for Swift 2.0:
var attrStr = try! NSAttributedString(
data: "<b><i>text</i></b>".dataUsingEncoding(NSUnicodeStringEncoding, allowLossyConversion: true)!,
options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
label.attributedText = attrStr
Swift 4
import UIKit
let htmlString = "<html><body> Some <b>html</b> string </body></html>"
// works even without <html><body> </body></html> tags, BTW
let data = htmlString.data(using: String.Encoding.unicode)! // mind "!"
let attrStr = try? NSAttributedString( // do catch
data: data,
options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html],
documentAttributes: nil)
// suppose we have an UILabel, but any element with NSAttributedString will do
label.attributedText = attrStr
Supplement: controlling the font of resulting formatted string
To use properly scaled (i.e. with respect to user settings) system (or any other) font you may do the following.
let newFont = UIFontMetrics.default.scaledFont(for: UIFont.systemFont(ofSize: UIFont.systemFontSize)) // The same is possible for custom font.
let mattrStr = NSMutableAttributedString(attributedString: attrStr!)
mattrStr.beginEditing()
mattrStr.enumerateAttribute(.font, in: NSRange(location: 0, length: mattrStr.length), options: .longestEffectiveRangeNotRequired) { (value, range, _) in
if let oFont = value as? UIFont, let newFontDescriptor = oFont.fontDescriptor.withFamily(newFont.familyName).withSymbolicTraits(oFont.fontDescriptor.symbolicTraits) {
let nFont = UIFont(descriptor: newFontDescriptor, size: newFont.pointSize)
mattrStr.removeAttribute(.font, range: range)
mattrStr.addAttribute(.font, value: nFont, range: range)
}
}
mattrStr.endEditing()
label.attributedText = mattrStr
You could try an attributed string:
var attrStr = NSAttributedString(
data: "<b><i>text</i></b>".dataUsingEncoding(NSUnicodeStringEncoding, allowLossyConversion: true),
options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil,
error: nil)
label.attributedText = attrStr
Objective-C Version:
NSError *error = nil;
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithData:contentData
options:#{NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType}
documentAttributes:nil error:&error];
This is just the Objective-C conversion of the above answers. All the answers above are right and reference taken from the above answers for this.
For me, Paul's answer worked. But for custom fonts I had to put following hack.
//Please take care of force unwrapping
let data = htmlString.data(using: String.Encoding.unicode)!
let mattrStr = try! NSMutableAttributedString(
data: data,
options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html],
documentAttributes: nil)
let normalFont = UIFontMetrics.default.scaledFont(for: UIFont(name: "NormalFontName", size: 15.0)!)//
let boldFont = UIFontMetrics.default.scaledFont(for: UIFont(name: "BoldFontName", size: 15.0)!)
mattrStr.beginEditing()
mattrStr.enumerateAttribute(.font, in: NSRange(location: 0, length: mattrStr.length), options: .longestEffectiveRangeNotRequired) { (value, range, _) in
if let oFont = value as? UIFont{
mattrStr.removeAttribute(.font, range: range)
if oFont.fontName.contains("Bold"){
mattrStr.addAttribute(.font, value: boldFont, range: range)
}
else{
mattrStr.addAttribute(.font, value: normalFont, range: range)
}
}
}
Try this:
let label : UILable! = String.stringFromHTML("html String")
func stringFromHTML( string: String?) -> String
{
do{
let str = try NSAttributedString(data:string!.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true
)!, options:[NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: NSNumber(unsignedLong: NSUTF8StringEncoding)], documentAttributes: nil)
return str.string
} catch
{
print("html error\n",error)
}
return ""
}
Hope its helpful.