Rich Text Editor for iOS using WKWebView
If you are a iOS engineer working for a tech company like HubSpot, where the product main access point is a browser, the chances that you will have to deal with HTML/CSS are very high. In some sections of HubSpot there are text fields (see image below) where content is html and styling is handled via CSS.
While building the HubSpot iOS app we needed a text field able to display content created from the web version and vice versa, able to create content that web version can consume. Summarizing the text field has to satisfy the following requirements:
- Multi-line support
- Display HTML
- Basic CSS support
- Bold, italic and underline styles support (BIU)
The first thing that I tried was
NSAttributedString which can be used to display HTML passing
NSDocumentTypeDocumentAttribute. The problem with
UITextView is that it doesn’t support the CSS styles needed to create the annotation in the image below.
Also there’s no way to select BIU out of the box, and you will need to implement a custom
UIToolBar and assign it to the
inputAccessoryView property. We needed something else to solve this problem and so we started to look for rich text editors.
If you google for rich text editors you will find some implementations that are using a
UIWebView. By using a webview you will get full HTML/CSS support so we gave it a shot. For apps running on iOS 8 and later Apple recommends to use
WKWebView and Swift.
We need three things:
- HTML page containing a
UIViewthat wraps the
For the HTML page we can use a basic template like this:
When you tap on a webview showing a
contenteditable element the system will automatically present the keyboard and you will also get BIU styles from the long press menu.
One of the things that I really like about
UIWebView the only way is by changing
window.location passing the required parameters in the query string and implementing
WKWebView we have a new set of tools for achieve this:
func add(_ scriptMessageHandler: WKScriptMessageHandler, name: String) we can add a message handler that will result in exposing a function
WKScriptMessageHandler is a protocol that contains a single function and this function gets called, on the conforming object, each time you use
WKScriptMessage object is an object that encapsulates the message body and the message name.
Putting it all together we can create a re-useable rich text component that subclasses
UIView. The class exposes a text, height and placeholder properties and it also has a delegate property used to notify text and height change. You can find the implementation here.
We can use this view like any other
UIView and set the delegate if you need to handle dynamic height and retrieve the content text. One important thing that you need to watch out for is the
userContentController strong reference to the message handler. This is the reason behind the use of
The gif below shows the final result using random HTML. As you can see it handles many HTML/CSS combinations very well.
Any of this sound interesting? HubSpot is hiring iOS developers! You can find more details here.