I have some HTML data, which contains headings, paragraphs , images and lists tags.
Is there a way to display this data in one UITextView
or UILabel
?
This question is related to
html
ios
swift
uitextview
nsattributedstring
Display images and text paragraphs is not possible in a UITextView
or UILabel
, to this, you must use a UIWebView
.
Just add the item in the storyboard, link to your code, and call it to load the URL.
OBJ-C
NSString *fullURL = @"http://conecode.com";
NSURL *url = [NSURL URLWithString:fullURL];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[_viewWeb loadRequest:requestObj];
Swift
let url = NSURL (string: "http://www.sourcefreeze.com");
let requestObj = NSURLRequest(URL: url!);
viewWeb.loadRequest(requestObj);
Step by step tutorial. http://sourcefreeze.com/uiwebview-example-using-swift-in-ios/
Thx for the above answer here is Swift 4.2
extension String {
var htmlToAttributedString: NSAttributedString? {
guard
let data = self.data(using: .utf8)
else { return nil }
do {
return try NSAttributedString(data: data, options: [
NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html,
NSAttributedString.DocumentReadingOptionKey.characterEncoding: String.Encoding.utf8.rawValue
], documentAttributes: nil)
} catch let error as NSError {
print(error.localizedDescription)
return nil
}
}
var htmlToString: String {
return htmlToAttributedString?.string ?? ""
}
}
Swift 5
extension UIColor {
var hexString: String {
let components = cgColor.components
let r: CGFloat = components?[0] ?? 0.0
let g: CGFloat = components?[1] ?? 0.0
let b: CGFloat = components?[2] ?? 0.0
let hexString = String(format: "#%02lX%02lX%02lX", lroundf(Float(r * 255)), lroundf(Float(g * 255)),
lroundf(Float(b * 255)))
return hexString
}
}
extension String {
func htmlAttributed(family: String?, size: CGFloat, color: UIColor) -> NSAttributedString? {
do {
let htmlCSSString = "<style>" +
"html *" +
"{" +
"font-size: \(size)pt !important;" +
"color: #\(color.hexString) !important;" +
"font-family: \(family ?? "Helvetica"), Helvetica !important;" +
"}</style> \(self)"
guard let data = htmlCSSString.data(using: String.Encoding.utf8) else {
return nil
}
return try NSAttributedString(data: data,
options: [.documentType: NSAttributedString.DocumentType.html,
.characterEncoding: String.Encoding.utf8.rawValue],
documentAttributes: nil)
} catch {
print("error: ", error)
return nil
}
}
}
And final you can create UILabel:
func createHtmlLabel(with html: String) -> UILabel {
let htmlMock = """
<b>hello</b>, <i>world</i>
"""
let descriprionLabel = UILabel()
descriprionLabel.attributedText = htmlMock.htmlAttributed(family: "YourFontFamily", size: 15, color: .red)
return descriprionLabel
}
Result:
See tutorial:
https://medium.com/@valv0/a-swift-extension-for-string-and-html-8cfb7477a510
IF YOU HAVE A STRING WITH HTML CODE INSIDE YOU CAN USE:
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: [
.documentType: NSAttributedString.DocumentType.html,
.characterEncoding: String.Encoding.utf8.rawValue
], documentAttributes: nil)
} catch {
print(error.localizedDescription)
return nil
}
}
var htmlString: String {
return htmlAttributedString?.string ?? self
}
}
AND IN YOUR CODE YOU USE:
label.text = "something".htmlString
Add this extension to convert your html code to a regular string:
extension String {
var html2AttributedString: NSAttributedString? {
guard
let data = dataUsingEncoding(NSUTF8StringEncoding)
else { return nil }
do {
return try NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute:NSUTF8StringEncoding], documentAttributes: nil)
} catch let error as NSError {
print(error.localizedDescription)
return nil
}
}
var html2String: String {
return html2AttributedString?.string ?? ""
}
}
And then you show your String inside an UITextView Or UILabel
textView.text = yourString.html2String
or
label.text = yourString.html2String
For Swift 5, it also can load css.
extension String {
public var convertHtmlToNSAttributedString: NSAttributedString? {
guard let data = data(using: .utf8) else {
return nil
}
do {
return try NSAttributedString(data: data,options: [.documentType: NSAttributedString.DocumentType.html,.characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
}
catch {
print(error.localizedDescription)
return nil
}
}
public func convertHtmlToAttributedStringWithCSS(font: UIFont? , csscolor: String , lineheight: Int, csstextalign: String) -> NSAttributedString? {
guard let font = font else {
return convertHtmlToNSAttributedString
}
let modifiedString = "<style>body{font-family: '\(font.fontName)'; font-size:\(font.pointSize)px; color: \(csscolor); line-height: \(lineheight)px; text-align: \(csstextalign); }</style>\(self)";
guard let data = modifiedString.data(using: .utf8) else {
return nil
}
do {
return try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
}
catch {
print(error)
return nil
}
}
}
After that, go to your string you want to convert to NSAttributedString and place it like the example below:
myUILabel.attributedText = "Swift is awesome!!!".convertHtmlToAttributedStringWithCSS(font: UIFont(name: "Arial", size: 16), csscolor: "black", lineheight: 5, csstextalign: "center")
Here’s what every parameter takes:
I had problems to change attributes of text after that, and I could see others asking why...
So best answer is to use extension with NSMutableAttributedString instead:
extension String {
var htmlToAttributedString: NSMutableAttributedString? {
guard let data = data(using: .utf8) else { return nil }
do {
return try NSMutableAttributedString(data: data,
options: [.documentType: NSMutableAttributedString.DocumentType.html,
.characterEncoding: String.Encoding.utf8.rawValue],
documentAttributes: nil)
} catch let error as NSError {
print(error.localizedDescription)
return nil
}
}
}
And then you can use it this way:
if let labelTextFormatted = text.htmlToAttributedString {
let textAttributes = [
NSAttributedStringKey.foregroundColor: UIColor.white,
NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 13)
] as [NSAttributedStringKey: Any]
labelTextFormatted.addAttributes(textAttributes, range: NSRange(location: 0, length: labelTextFormatted.length))
self.contentText.attributedText = labelTextFormatted
}
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.
Swift 3.0
var attrStr = try! NSAttributedString(
data: "<b><i>text</i></b>".data(using: String.Encoding.unicode, allowLossyConversion: true)!,
options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
label.attributedText = attrStr
Swift 3
extension String {
var html2AttributedString: NSAttributedString? {
guard
let data = data(using: String.Encoding.utf8)
else { return nil }
do {
return try NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute:String.Encoding.utf8], documentAttributes: nil)
} catch let error as NSError {
print(error.localizedDescription)
return nil
}
}
var html2String: String {
return html2AttributedString?.string ?? ""
}
}
I'm using this:
extension UILabel {
func setHTML(html: String) {
do {
let attributedString: NSAttributedString = try NSAttributedString(data: html.data(using: .utf8)!, options: [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType], documentAttributes: nil)
self.attributedText = attributedString
} catch {
self.text = html
}
}
}
If you want HTML, with images and a list, this isn't support by UILabel. However, I've found YYText does the trick.
Swift 5
extension String {
func htmlAttributedString() -> NSAttributedString? {
guard let data = self.data(using: String.Encoding.utf16, allowLossyConversion: false) else { return nil }
guard let html = try? NSMutableAttributedString(
data: data,
options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html],
documentAttributes: nil) else { return nil }
return html
}
}
Call:
myLabel.attributedText = "myString".htmlAttributedString()
Here is a Swift 3 version:
private func getHtmlLabel(text: String) -> UILabel {
let label = UILabel()
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.attributedString = stringFromHtml(string: text)
return label
}
private func stringFromHtml(string: String) -> NSAttributedString? {
do {
let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true)
if let d = data {
let str = try NSAttributedString(data: d,
options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
return str
}
} catch {
}
return nil
}
I found issues with some of the other answers here and it took me a bit to get this right. I set the line break mode and number of lines so that the label sized appropriately when the HTML spanned multiple lines.
I know that this will look little over the top but ... This code will add html support to UILabel, UITextView, UIButton and you can easily add this support to any view that has attributed string support :
public protocol CSHasAttributedTextProtocol: AnyObject {
func attributedText() -> NSAttributedString?
func attributed(text: NSAttributedString?) -> Self
}
extension UIButton: CSHasAttributedTextProtocol {
public func attributedText() -> NSAttributedString? {
attributedTitle(for: .normal)
}
public func attributed(text: NSAttributedString?) -> Self {
setAttributedTitle(text, for: .normal); return self
}
}
extension UITextView: CSHasAttributedTextProtocol {
public func attributedText() -> NSAttributedString? { attributedText }
public func attributed(text: NSAttributedString?) -> Self { attributedText = text; return self }
}
extension UILabel: CSHasAttributedTextProtocol {
public func attributedText() -> NSAttributedString? { attributedText }
public func attributed(text: NSAttributedString?) -> Self { attributedText = text; return self }
}
public extension CSHasAttributedTextProtocol
where Self: CSHasFontProtocol, Self: CSHasTextColorProtocol {
@discardableResult
func html(_ text: String) -> Self { html(text: text) }
@discardableResult
func html(text: String) -> Self {
let html = """
<html><body style="color:\(textColor!.hexValue()!);
font-family:\(font()!.fontName);
font-size:\(font()!.pointSize);">\(text)</body></html>
"""
html.data(using: .unicode, allowLossyConversion: true).notNil { data in
attributed(text: try? NSAttributedString(data: data, options: [
.documentType: NSAttributedString.DocumentType.html,
.characterEncoding: NSNumber(value: String.Encoding.utf8.rawValue)
], documentAttributes: nil))
}
return self
}
}
public protocol CSHasFontProtocol: AnyObject {
func font() -> UIFont?
func font(_ font: UIFont?) -> Self
}
extension UIButton: CSHasFontProtocol {
public func font() -> UIFont? { titleLabel?.font }
public func font(_ font: UIFont?) -> Self { titleLabel?.font = font; return self }
}
extension UITextView: CSHasFontProtocol {
public func font() -> UIFont? { font }
public func font(_ font: UIFont?) -> Self { self.font = font; return self }
}
extension UILabel: CSHasFontProtocol {
public func font() -> UIFont? { font }
public func font(_ font: UIFont?) -> Self { self.font = font; return self }
}
public protocol CSHasTextColorProtocol: AnyObject {
func textColor() -> UIColor?
func text(color: UIColor?) -> Self
}
extension UIButton: CSHasTextColorProtocol {
public func textColor() -> UIColor? { titleColor(for: .normal) }
public func text(color: UIColor?) -> Self { setTitleColor(color, for: .normal); return self }
}
extension UITextView: CSHasTextColorProtocol {
public func textColor() -> UIColor? { textColor }
public func text(color: UIColor?) -> Self { textColor = color; return self }
}
extension UILabel: CSHasTextColorProtocol {
public func textColor() -> UIColor? { textColor }
public func text(color: UIColor?) -> Self { textColor = color; return self }
}
Source: Stackoverflow.com