Swift: 在标签或 textView 中显示 HTML 数据

我有一些 HTML 数据,其中包含标题,段落,图片和列表标签。

有没有办法在一个 UITextViewUILabel中显示这些数据?

149943 次浏览

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.

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

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/

If you want HTML, with images and a list, this isn't support by UILabel. However, I've found YYText does the trick.

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.

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

For Swift 5:

extension String {
var htmlToAttributedString: 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 {
return nil
}
}
var htmlToString: String {
return htmlToAttributedString?.string ?? ""
}
}

Then, whenever you want to put HTML text in a UITextView use:

textView.attributedText = htmlText.htmlToAttributedString

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
}

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

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

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()

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:

enter image description here

See tutorial:

https://medium.com/@valv0/a-swift-extension-for-string-and-html-8cfb7477a510

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&#33;&#33;&#33;".convertHtmlToAttributedStringWithCSS(font: UIFont(name: "Arial", size: 16), csscolor: "black", lineheight: 5, csstextalign: "center")

enter image description here Here’s what every parameter takes:

  • font: Add your font as usually do in a UILabel/UITextView, using UIFont with the name of your custom font and the size.
  • csscolor: Either add color in HEX format, like "#000000" or use the name of the color, like "black".
  • lineheight: It’s the space between the lines when you have multiple lines in a UILabel/UITextView.
  • csstextalign: It’s the alignment of the text, the value that you need to add is "left" or "right" or "center" or "justify"

Reference: https://johncodeos.com/how-to-display-html-in-uitextview-uilabel-with-custom-color-font-etc-in-ios-using-swift/

extension UITextView {
func setHTMLFromString(htmlText: String) {
let modifiedFont = String(format:"<span style=\"font-family: '-apple-system', 'HelveticaNeue'; font-size: \(self.font!.pointSize)\">%@</span>", htmlText)


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


self.attributedText = attrStr
}
}