Раньше мне было сложно понять, как работать с «#» и «@», но я, наконец, нашел хороший метод работы.

Установка

Во-первых, это лучше всего работает в TextView. Поэтому настройте его внутри вашего представления, как хотите, но убедитесь, что ваш ViewController имеет UITextViewDelegate, а textView делегирован этому контроллеру представления.

Я также делаю это с некоторой предварительно заполненной информацией, но та же концепция применима к извлечению данных из вашей базы данных и тому подобное.

[Ради учебника я настроил свой textView с помощью раскадровки. Быстро и просто. Не трогай меня.]

Вот как мы настраиваем наш ViewController:

class ViewController: UIViewController, UITextViewDelegate {
    var string = "Hello, my name is @Jared & #Jared and I like to move it."
    @IBOutlet weak var textView: UITextView!
    override func viewDidLoad() {
        super.viewDidLoad()
        textView.text = string
        textView.delegate = self
    }
...

Разрешение символов

Теперь мы переходим к самым серьезным вещам! (Ву!)

Общая задача, которую мы пытаемся решить в этой части, - просто разделить все слова в нашем textView. Это проще, чем вы думаете:

Во-первых, давайте создадим наше расширение:

extension UITextView {
   func resolveTags(){

[Забегая вперед, это просто добавление материала в функцию resolveTags, пока я не укажу обратное]

Преобразуйте нашу строку в NSString. Это позволяет разделить компоненты.

let nsText:NSString = self.text as NSString

Разделите слова, используя .compenents (separatedBy: ««) ‹- Включите этот пробел в кавычки. Это позволит нам разделить отдельные слова.

let words:[String] = nsText.components(separatedBy: " ")

Настройте пару атрибутов для того, как вы хотите, чтобы ваш текст выглядел в TextView. Эти атрибуты будут применены к любому TextView, для которого вы вызываете resolveTags, поэтому сделайте:

let attrs = [
       NSAttributedStringKey.font : UIFont.init(name: "HelveticaNeue", size: 13),
       NSAttributedStringKey.foregroundColor : UIColor.black
]

После создания этих атрибутов нам теперь нужно передать их и наш nsText в NSMutableAttributedString. Это позволит нам добавить крутые синие блики и сделать его интерактивным.

let attrString = NSMutableAttributedString(string: nsText as String, attributes:attrs)

Затем мы перебираем слова и проверяем префиксы. Сначала мы будем работать только с "#"

for word in words {
    if word.hasPrefix("#") {

Затем нам нужно получить диапазон символов, который мы хотим добавить для нашей кликабельности:

let matchRange:NSRange = nsText.range(of: word as String)

Затем мы преобразуем наше слово в String, а не в NSString. Это позволит нам отбросить «#» в начале нашего значения. Таким образом, вместо того, чтобы получать @jared при нажатии, вы фактически получаете просто «jared».

var stringifiedWord:String = word as String
stringifiedWord = String(stringifiedWord.dropFirst())

Затем мы добавляем пару атрибутов в нашу attrString. Здесь мы просто добавляем ссылку и ее диапазон. Убедитесь, что ваше значение установлено на «hash: \ (stringifiedWord)». Наличие этого «хеша» впереди позволит нам позже возиться с вещами, когда мы сделаем его кликабельным.

attrString.addAttribute(NSAttributedStringKey.link, value: "hash:\(stringifiedWord)", range: matchRange)

Наконец, мы придаем ему сладкий, сладко-голубой цвет. 👌

attrString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.blue , range: matchRange)

Теперь мы делаем то же самое для нашего символа «@».

 } else if word.hasPrefix("@") {
      let matchRange:NSRange = nsText.range(of: word as String)
      var stringifiedWord:String = word as String
      stringifiedWord = String(stringifiedWord.dropFirst())
      attrString.addAttribute(NSAttributedStringKey.link, value: "user:\(stringifiedWord)", range: matchRange)
      attrString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.blue , range: matchRange)
}

Наконец, ОЧЕНЬ важный шаг, мы применяем нашу attrString к нашему textView. 💪

self.attributedText = attrString
} // Close up your resolveTags function.

Давай воспользуемся этой штукой!

Все сводится к этому. У нас есть эта функция, как теперь ее использовать?

Легкий.

Внутри вашей функции viewDidLoad или где бы вы ни установили текст textView, просто вызовите:

textView.resolveTags()

Это дает вам такой результат ... НО вы пока не можете нажимать на эти элементы. Почему?!

Перестань беспокоиться.

Все, что нам нужно сделать, это добавить эту функцию:

func textView(_ textView: UITextView, shouldInteractWith touchedURL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {

Если вы - делегат textView, настроенный для вашего ViewController, как я уже говорил вам ранее (что вы следовали идеально… верно?), Эта функция будет вызываться при нажатии одного из этих выделенных слов. Теперь давайте добавим сюда логику для обработки этих нажатий:

if touchedURL.absoluteString.contains("hash:") {
print("HASHTAG") // This is where you move onto another view or do something mind-blowing.
}
else if touchedURL.absoluteString.contains("user:") {
print("USER") // This is where you move onto another view or do something mind-blowing.
}
return true

Если у вас возникли проблемы с нажатием на текст, попробуйте включить isSelectable и выключить isEditable.

Вот и все!

Теперь ты можешь веселиться, как будто завтра не наступит, мой друг, потому что теперь у тебя все работает. Если это помогло и вы чувствуете себя щедрым, поддержите мои усилия! :]