Since there were no ready-made solutions satisfying all my requests, I had to write the method itself.

Maybe someone will come in handy.
import UIKit class ViewController: UIViewController { @IBOutlet weak var TestTextView: UITextView! @IBOutlet weak var edittext: UITextView! @IBAction func buttonPressed(sender: UIButton) { TestTextView.attributedText = getColoredText(edittext.text) } override func viewDidLoad() { super.viewDidLoad() //ΠΠ°ΡΡΡΠ°ΠΈΠ²Π°Π΅ΠΌ ΡΠ°ΡΠΏΠΎΠ·Π½Π°Π²Π°Π½ΠΈΠ΅ Π½Π°ΠΆΠ°ΡΠΈΠΉ TestTextView.userInteractionEnabled = true let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.textViewTap(_:))) TestTextView.addGestureRecognizer(tapGesture) //Π Π°ΡΠΊΡΠ°ΡΠΈΠ²Π°Π΅ΠΌ ΡΠ΅ΠΊΡΡ TestTextView.attributedText = getColoredText(TestTextView.text) } let hashtagCalloutColor = UIColor(colorLiteralRed: 0, green: 0.73, blue: 0.66, alpha: 1) //00BAA9 func getColoredText(text:String) -> NSMutableAttributedString{ let string = NSMutableAttributedString(string: text) //ΠΠ°Ρ
ΠΎΠ΄ΠΈΠΌ Π²ΡΠ΅ Ρ
Π΅ΡΡΠ΅Π³ΠΈ ΠΈ ΡΠΏΠΎΠΌΠΈΠ½Π°Π½ΠΈΡ ΠΈ ΠΊΡΠ°ΡΠΈΠΌ ΠΈΡ
Π² Π½ΡΠΆΠ½ΡΠΉ ΡΠ²Π΅Ρ let pat = "[#]\\w+|[@]\\w+" let regex = try! NSRegularExpression(pattern: pat, options: []) let matches = regex.matchesInString(string.string, options: [], range: NSRange(location: 0, length: string.length)) //ΠΠ΄Π΅ΡΡ ΠΌΡ ΠΏΡΠΎΡ
ΠΎΠ΄ΠΈΠΌ ΠΏΠΎ Π²ΡΠ΅ΠΌ Π½Π°ΠΉΠ΄Π΅Π½ΡΠΌ ΡΠ»ΠΎΠ²Π°ΠΌ ΠΈ ΠΊΡΠ°ΡΠΈΠΌ ΠΈΡ
if matches.count > 0 { for match in matches { string.addAttribute(NSForegroundColorAttributeName, value: hashtagCalloutColor, range: match.range) } } return string } func getWordForIndex(string string: String, index: Int) -> String { var startInd = index var endInd = 0 let stringLngt = string.characters.count if stringLngt == index + 1 {endInd = index} else if stringLngt > index + 1 { endInd = index for i in index + 2 ... stringLngt { let x = i - 1 let charctr = string[string.startIndex.advancedBy(x)] if charctr != " " && charctr != "," && charctr != "\n" && i != stringLngt {endInd += 1} else { endInd = x break } } } if index > 0 { for i in 1 ... index { let x = index - i let charctr = string[string.startIndex.advancedBy(x)] if charctr != " " && charctr != "\n" {startInd -= 1} else {break} } } if endInd < stringLngt - 1 { return string.substringWithRange(string.startIndex.advancedBy(startInd)..<string.startIndex.advancedBy(endInd)) } else { return string.substringWithRange(string.startIndex.advancedBy(startInd)..<string.endIndex) } } func textViewTap(gestureRecognizer: UIGestureRecognizer) { let myTextView = gestureRecognizer.view as! UITextView let layoutManager = myTextView.layoutManager // location of tap in myTextView coordinates and taking the inset into account var location = gestureRecognizer.locationInView(myTextView) //.location(in: myTextView) location.x -= myTextView.textContainerInset.left location.y -= myTextView.textContainerInset.top // character index at tap location let characterIndex = layoutManager.characterIndexForPoint(location, inTextContainer: myTextView.textContainer, fractionOfDistanceBetweenInsertionPoints: nil) let word = getWordForIndex(string: myTextView.text, index: characterIndex) if word.hasPrefix("#") { print("hashtag = \(word)") } if word.hasPrefix("@") { print("mention = \(word)") } } }