     }
 }
 
-private struct TextViewCharacterFinder: CharacterFinder {
-    typealias ViewType = UITextView
-
+extension UITextView: CharacterFinder {
     /**
      Finds the character at a given location in a tapped view.
 
-     :param: view        The view that was tapped. Must be an instance of UITextView.
-     :param: tapLocation The location of the tap. Usually derived from a gesture recognizer.
-
-     :returns: The index of the tapped character.
+     - parameter 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 {
-
+    public func indexOfTappedCharacter(tapLocation: CGPoint) -> Int {
         // Location of the tap
 
         var location = tapLocation
-        let layoutManager = view.layoutManager
-        location.x -= view.textContainerInset.left
-        location.y -= view.textContainerInset.top
+        location.x -= textContainerInset.left
+        location.y -= textContainerInset.top
 
         // Find the tapped character
 
-        return layoutManager.characterIndexForPoint(location, inTextContainer: view.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
-    }
-}
-
-private struct TextFieldCharacterFinder: CharacterFinder {
-    typealias ViewType = UITextField
-
+        return layoutManager.characterIndexForPoint(location, inTextContainer: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
+    }
+}
+
+extension UITextField: CharacterFinder {
     /**
      Finds the character at a given location in a tapped view.
 
-     :param: view        The view that was tapped. Must be an instance of UITextField.
-     :param: tapLocation The location of the tap. Usually derived from a gesture recognizer.
-
-     :returns: The index of the tapped character.
+     - parameter 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 {
-
+    public func indexOfTappedCharacter(tapLocation: CGPoint) -> Int {
         // UITextField doesn't come with NSTextStorage, NSTextContainer, or NSLayoutManager, so
         // we have to create these manually.
 
         var charIndex = -1
 
-        if let attributedText = view.attributedText {
+        if let attributedText = m_attributedText {
             let textStorage = NSTextStorage(attributedString: attributedText)
             let layoutManager = NSLayoutManager()
             textStorage.addLayoutManager(layoutManager)
 
-            let textContainer = NSTextContainer(size: view.bounds.size)
+            let textContainer = NSTextContainer(size: bounds.size)
             textContainer.lineFragmentPadding = 0
             textContainer.layoutManager = layoutManager
-            
+
             layoutManager.addTextContainer(textContainer)
             layoutManager.textStorage = textStorage
-            
+
             // Find the tapped character
-            
+
             charIndex = layoutManager.characterIndexForPoint(tapLocation, inTextContainer: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
         }
-        
+
         return charIndex
     }
 }

    func viewTapped(recognizer: UITapGestureRecognizer) {
        recognizer.cancelsTouchesInView = false

        let view = recognizer.view!
        let location = recognizer.locationInView(view)
        var charIndex: Int?
        var attributedString: NSAttributedString?

        switch view {
        case let label as UILabel:
            charIndex = LabelCharacterFinder.indexOfTappedCharacter(inView: label, tapLocation: location)
            attributedString = label.attributedText
        case let textView as UITextView:
            charIndex = TextViewCharacterFinder.indexOfTappedCharacter(inView: textView, tapLocation: location)
            attributedString = textView.attributedText
        case let textField as UITextField:
            charIndex = TextFieldCharacterFinder.indexOfTappedCharacter(inView: textField, tapLocation: location)
            attributedString = textField.attributedText
        default:
            print("unsupported view")
        }

        if let index = charIndex {
            if let userId = attributedString?.attribute(MentionAttributes.UserId, atIndex: index, effectiveRange: nil) as? String {
                delegate?.userTappedWithId(userId)
                recognizer.cancelsTouchesInView = true
            }
        }
    }
}

///  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<T: UIView where T: AttributedTextContainingView, T: CharacterFinder>: NSObject, MentionTapHandlerDelegate {

    var view: AttributedTextContainingView
    weak var delegate: MentionTapHandlerDelegate?
    private var tapHandler: MentionTapHandler<T>!
    private let mentionDecoder: MentionDecoder

    // MARK: Init
