Обнаружение нажатий на текст с атрибутами с помощью Swift
Иногда новичкам бывает сложно понять, как все настроить (по крайней мере, это было для меня), поэтому этот пример немного полнее.
Добавьте UITextView
в свой проект.
Торговая точка
Подключите UITextView
к ViewController
розетке с именем textView
.
Настраиваемый атрибут
Мы собираемся создать собственный атрибут, сделав расширение .
Примечание. Этот шаг технически необязателен, но если вы этого не сделаете, вам нужно будет отредактировать код в следующей части, чтобы использовать стандартный атрибут, например NSAttributedString.Key.foregroundColor
. Преимущество использования настраиваемого атрибута заключается в том, что вы можете определить, какие значения вы хотите сохранить в текстовом диапазоне с атрибутами.
Добавьте новый быстрый файл с помощью File> New> File ...> iOS> Source> Swift File . Вы можете называть это как хотите. Я называю свой NSAttributedStringKey + CustomAttribute.swift .
Вставьте следующий код:
import Foundation
extension NSAttributedString.Key {
static let myAttributeName = NSAttributedString.Key(rawValue: "MyCustomAttribute")
}
Код
Замените код в ViewController.swift следующим. Обратите внимание на расширение UIGestureRecognizerDelegate
.
import UIKit
class ViewController: UIViewController, UIGestureRecognizerDelegate {
@IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
// Create an attributed string
let myString = NSMutableAttributedString(string: "Swift attributed text")
// Set an attribute on part of the string
let myRange = NSRange(location: 0, length: 5) // range of "Swift"
let myCustomAttribute = [ NSAttributedString.Key.myAttributeName: "some value"]
myString.addAttributes(myCustomAttribute, range: myRange)
textView.attributedText = myString
// Add tap gesture recognizer to Text View
let tap = UITapGestureRecognizer(target: self, action: #selector(myMethodToHandleTap(_:)))
tap.delegate = self
textView.addGestureRecognizer(tap)
}
@objc func myMethodToHandleTap(_ sender: UITapGestureRecognizer) {
let myTextView = sender.view as! UITextView
let layoutManager = myTextView.layoutManager
// location of tap in myTextView coordinates and taking the inset into account
var location = sender.location(in: myTextView)
location.x -= myTextView.textContainerInset.left;
location.y -= myTextView.textContainerInset.top;
// character index at tap location
let characterIndex = layoutManager.characterIndex(for: location, in: myTextView.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
// if index is valid then do something.
if characterIndex < myTextView.textStorage.length {
// print the character index
print("character index: \(characterIndex)")
// print the character at the index
let myRange = NSRange(location: characterIndex, length: 1)
let substring = (myTextView.attributedText.string as NSString).substring(with: myRange)
print("character at index: \(substring)")
// check if the tap location has a certain attribute
let attributeName = NSAttributedString.Key.myAttributeName
let attributeValue = myTextView.attributedText?.attribute(attributeName, at: characterIndex, effectiveRange: nil)
if let value = attributeValue {
print("You tapped on \(attributeName.rawValue) and the value is: \(value)")
}
}
}
}
Теперь, если вы нажмете на «w» в «Swift», вы должны получить следующий результат:
character index: 1
character at index: w
You tapped on MyCustomAttribute and the value is: some value
Ноты
- Здесь я использовал настраиваемый атрибут, но с таким же успехом он мог быть
NSAttributedString.Key.foregroundColor
(цвет текста) со значением UIColor.green
.
- Раньше текстовое представление нельзя было редактировать или выбирать, но в моем обновленном ответе для Swift 4.2 он, похоже, работает нормально независимо от того, выбраны они или нет.
Дальнейшее обучение
Этот ответ был основан на нескольких других ответах на этот вопрос. Помимо этого, см. Также