Wykrywanie dotknięć przypisanego tekstu za pomocą Swift
Czasami początkującym jest trochę trudno wiedzieć, jak to zrobić (i tak było dla mnie), więc ten przykład jest trochę pełniejszy.
Dodaj UITextView
do swojego projektu.
Wylot
Podłącz UITextView
do ViewController
z gniazdem o nazwietextView
.
Atrybut niestandardowy
Zamierzamy utworzyć atrybut niestandardowy, tworząc rozszerzenie .
Uwaga: ten krok jest technicznie opcjonalny, ale jeśli tego nie zrobisz, będziesz musiał edytować kod w następnej części, aby użyć standardowego atrybutu, takiego jak NSAttributedString.Key.foregroundColor
. Zaletą używania atrybutu niestandardowego jest to, że możesz określić, jakie wartości chcesz przechowywać w przypisanym zakresie tekstowym.
Dodaj nowy plik Swift za pomocą polecenia Plik> Nowy> Plik ...> iOS> Źródło> Swift Plik . Możesz to nazwać, jak chcesz. Nazywam mój NSAttributedStringKey + CustomAttribute.swift .
Wklej następujący kod:
import Foundation
extension NSAttributedString.Key {
static let myAttributeName = NSAttributedString.Key(rawValue: "MyCustomAttribute")
}
Kod
Zastąp kod w ViewController.swift następującym. Zwróć uwagę na 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)")
}
}
}
}
Jeśli teraz dotkniesz „w” opcji „Swift”, powinieneś otrzymać następujący wynik:
character index: 1
character at index: w
You tapped on MyCustomAttribute and the value is: some value
Uwagi
- Tutaj użyłem atrybutu niestandardowego, ale równie łatwo mógł
NSAttributedString.Key.foregroundColor
(kolor tekstu) mieć wartość UIColor.green
.
- Wcześniej widoku tekstu nie można było edytować ani wybierać, ale w mojej zaktualizowanej odpowiedzi dla Swift 4.2 wydaje się, że działa dobrze, niezależnie od tego, czy są one zaznaczone, czy nie.
Dalsze badanie
Ta odpowiedź została oparta na kilku innych odpowiedziach na to pytanie. Oprócz tego zobacz także