 ///  The MentionController class provides a simple interface for rendering @mentions and #hashtag comments on UILabel, UITextField, and UITextView.
 ///  To handle user taps on an @mentioin or #hashtag you must conform to the MentionTapHandlerDelegate protocol and set the delegate on MentionController.
 ///  Note: MentionController is built to be compatible objective C.
-public class MentionController: NSObject, MentionTapHandlerDelegate {
+public class MentionController<T: UIView where T: AttributedTextContainingView, T: CharacterFinder>: NSObject, MentionTapHandlerDelegate {
 
     var view: AttributedTextContainingView
     weak var delegate: MentionTapHandlerDelegate?
-    private var tapHandler: MentionTapHandler!
+    private var tapHandler: MentionTapHandler<T>!
     private let mentionDecoder: MentionDecoder
 
     // MARK: Init

*  CharacterFinder is a protocol for a class that identifies what character was tapped in the given container of text.
The container class type is at the discretion of the class or struct that implements CharacterFinder.
*/
private protocol CharacterFinder {
    typealias ViewType: AttributedTextContainingView
    static func indexOfTappedCharacter(inView view: ViewType, tapLocation: CGPoint) -> Int
}

private struct LabelCharacterFinder: CharacterFinder {
    typealias ViewType = UILabel

    /**
     Finds the character at a given location in a tapped view.

     :param: view        The view that was tapped. Must be an instance of UILabel.
     :param: tapLocation The location of the tap. Usually derived from a gesture recognizer.

     :returns: The index of the tapped character.
     */
    static func indexOfTappedCharacter(inView view: ViewType, tapLocation: CGPoint) -> Int {

        // UILabel doesn't come with NSTextStorage, NSTextContainer, or NSLayoutManager, so
        // we have to create these manually.

        let attributedText = view.attributedText ?? NSAttributedString()
        let textStorage = NSTextStorage(attributedString: attributedText)
        let layoutManager = NSLayoutManager()
        textStorage.addLayoutManager(layoutManager)

        let textContainer = NSTextContainer(size: view.bounds.size)
        textContainer.lineFragmentPadding = 0
        textContainer.maximumNumberOfLines = view.numberOfLines
        textContainer.lineBreakMode = view.lineBreakMode
        textContainer.layoutManager = layoutManager

        layoutManager.addTextContainer(textContainer)


/// Listens for taps on the supplied view and calls the corresponding MentionTapHandlerDelegate method.
/// Note: Creates an instance of UITapGestureRecognizer on the supplied UIView.
public class MentionTapHandler<T: UIView where T: AttributedTextContainingView, T: CharacterFinder>: NSObject {

    var tapRecognizer: UITapGestureRecognizer!
    weak var delegate: MentionTapHandlerDelegate?
