Визначення натискань на атрибутований текст за допомогою Swift
Іноді для початківців важко знати, як зробити так, щоб налаштувати речі (це все одно було для мене), тому цей приклад трохи повніше.
Додайте UITextView
до свого проекту.
Розетка
Підключіть UITextView
до ViewController
розетки з назвою textView
.
Спеціальний атрибут
Ми збираємося зробити спеціальний атрибут, зробивши розширення .
Примітка. Цей крок є технічно необов'язковим, але якщо ви цього не зробите, вам потрібно буде відредагувати код у наступній частині, щоб використовувати стандартний атрибут типу NSAttributedString.Key.foregroundColor
. Перевага використання спеціального атрибута полягає в тому, що ви можете визначити, які значення потрібно зберігати в атрибутованому діапазоні тексту.
Додайте новий швидкий файл за допомогою Файл> Новий> Файл ...> iOS> Джерело> Файл Swift . Ви можете назвати його тим, що хочете. Я дзвоню мою 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, здається, він працює нормально, незалежно від того, вибрані вони чи ні.
Подальше навчання
Ця відповідь ґрунтувалася на кількох інших відповідях на це питання. Крім них, див. Також