Photo under CC by Jonathan Rolande
I’m a firm believer that native UI is superior to the web view experience on mobile. However, if you want rich-text user generated content support across both web and native platforms a markup language rendered natively is definitely the way to go. Trying to support the full-HTML standard natively sounds like a nightmare, but if you allow a restricted subset of the tags the problem becomes more manageable. In this article I’m going to walk through what solutions to HTML rendering exist on iOS and how I’ve implemented it under the intensive re-use / responsive scenario of rendering it in a UITableViewCell.
We can all imaging how writing our own HTML parsers using the attributed string API would a less than fun experience. Luckily there are a few frameworks available out there:
Taking a look at all of these approaches I found that the DTCoreText gave me responsiveness while saving me the time of writing a solution myself. Lets walk through implementing it!
I’m not going to cover each step in setting up a UITableViewController and UITableViewCell, but you can see how I have everything configured in the github example. The main parts you need to remember are to:
First thing to do is to define a configure function on the UITableViewCell where we will be implementing the rending code:
func configure(htmlText: String) { ...
The first thing you need to do is define your font and color via the options dictionary:
let color = UIColor.blueColor() let fontSize: Float = 12 var options = [ DTCoreTextStub.kDTCoreTextOptionKeyFontSize(): NSNumber(float: Float(fontSize)), DTCoreTextStub.kDTCoreTextOptionKeyFontName(): "HelveticaNeue", DTCoreTextStub.kDTCoreTextOptionKeyFontFamily(): "Helvetica Neue", DTCoreTextStub.kDTCoreTextOptionKeyUseiOS6Attributes(): NSNumber(bool: true), DTCoreTextStub.kDTCoreTextOptionKeyTextColor(): color] }
Now that we’ve defined the text style we can tell DTCoreText to create our attributed string:
let attributedString = DTCoreTextStub.attributedStringWithHtml(block.text, options: options)
Next, I’ve found it useful to clean up some of the extraneous new-lines that DTCoreText adds to keep our text field tight around the text:
let mutableAttributedString = NSMutableAttributedString(attributedString: attributedString) let range = NSMakeRange(0, attributedString.length) //Strip out the extraneous \n added by DTCoreText mutableAttributedString.mutableString.replaceOccurrencesOfString("\n", withString: "", options: NSStringCompareOptions.CaseInsensitiveSearch, range: range)
Lastly, you can apply any additional formatting you wish such as line spacing:
let stringRange = NSMakeRange(0, attrString.length) var style = NSMutableParagraphStyle() tyle.lineSpacing = 3.5 mutableAttributedString.addAttribute(NSParagraphStyleAttributeName, value: style, range: stringRange)
Finally we can render it in our UITextView:
textView.attributedText = mutableAttributedString
textView.scrollEnabled = false
textView.layoutManager.ensureLayoutForTextContainer(textView.textContainer) textView.layoutIfNeeded()
Now you should have a snappy UITableView that renders HTML natively. Check out the full example project on GitHub.