How to display HTML in UILabel and UITextView

UIKit HTML UILabel UITextView

When you work with an API, there would be a time when your backend wants to control a text style. HTML is the most common format for this kind of job. Do you know that WKWebView is not the only way to present HTML string? You can render HTML string directly on UILabel and UITextView.

HTML String #

A backend might return a response with something like this:

"This is a <b>bold</b> text."

Convert to NSAttributedString #

To render this text properly in UILabel or UITextView, you need to convert it to NSAttributedString. NSAttributedString has built-in support for this conversion.

First, we need to convert HTML string to Data.

let htmlString = "This is a <b>bold</b> text."
let data = htmlString.data(using: .utf8)!

Then we initialize NSAttributedString with the data and documentType option to .html.

let attributedString = try? NSAttributedString(
data: data,
options: [.documentType: NSAttributedString.DocumentType.html],
documentAttributes: nil)

After you get an attributed string, you can set it to UILabel or UITextView.

label.attributedText = attributedString

The result is quite ugly, as you might be expected.

Default style for html string
Default style for html string

Extension #

Before we fix the style problem, let's create an extension out of this.

extension String {
func htmlAttributedString() -> NSAttributedString? {
guard let data = self.data(using: .utf8) else {
return nil
}

return try? NSAttributedString(
data: data,
options: [.documentType: NSAttributedString.DocumentType.html],
documentAttributes: nil
)
}
}

Now, we can use it like this.

let htmlString = "This is a <b>bold</b> text."
label.attributedText = htmlString.htmlAttributedString()

Apply a style #

Since we are dealing with HTML, we can use CSS to apply a style to our attributed string. Simply create HTML boilerplate string and interpolate our content inside a body tag.

func htmlAttributedString() -> NSAttributedString? {
let htmlTemplate = """
<!doctype html>
<html>
<head>
<style>
body {
font-family: -apple-system;
font-size: 24px;
}
</style>
</head>
<body>
\(self)
</body>
</html>
"""

guard let data = htmlTemplate.data(using: .utf8) else {
return nil
}

guard let attributedString = try? NSAttributedString(
data: data,
options: [.documentType: NSAttributedString.DocumentType.html],
documentAttributes: nil
) else {
return nil
}

return attributedString
}
Attributed string with CSS as a style
Attributed string with CSS as a style

Parameterize #

You can make our extension accept parameters of size and color for the ease of use.

extension String {
func htmlAttributedString(size: CGFloat, color: UIColor) -> NSAttributedString? {
let htmlTemplate = """
<!doctype html>
<html>
<head>
<style>
body {
color: \(color.hexString!);
font-family: -apple-system;
font-size: \(size)px;
}
</style>
</head>
<body>
\(self)
</body>
</html>
"""

guard let data = htmlTemplate.data(using: .utf8) else {
return nil
}

guard let attributedString = try? NSAttributedString(
data: data,
options: [.documentType: NSAttributedString.DocumentType.html],
documentAttributes: nil
) else {
return nil
}

return attributedString
}
}

extension UIColor {
var hexString:String? {
if let components = self.cgColor.components {
let r = components[0]
let g = components[1]
let b = components[2]
return String(format: "#%02x%02x%02x", (Int)(r * 255), (Int)(g * 255), (Int)(b * 255))
}
return nil
}
}

You can use it like this:

label.attributedText = htmlString.htmlAttributedString2(size: 18, color: .systemPink)

Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.

If you enjoy this article, you can subscribe to the weekly newsletter.

Every Friday, you’ll get a quick recap of all articles and tips posted on this site — entirely for free.

← Home