iOS 13.2 UITextView附件交互新Bug:仅长按触发shouldInteract方法求解决方案
Hey there, sorry to hear you're stuck with another UITextView attachment quirk after the last one got sorted in iOS 13.2—those early iOS 13 releases really threw us for a loop with text component bugs! While we wait for Apple to push a fix, here are a couple of solid workarounds you can implement right now:
Workaround 1: Subclass UITextView to Intercept Touch Events
By overriding the touch handling methods in a custom UITextView subclass, you can manually detect taps on attachments and trigger your desired interaction logic. Here's how to do it:
class AttachmentFixTextView: UITextView { override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touch = touches.first else { super.touchesEnded(touches, with: event) return } let touchPoint = touch.location(in: self) guard let textPosition = closestPosition(to: touchPoint) else { super.touchesEnded(touches, with: event) return } // Check if the tapped position contains an attachment if let attachment = textStyling(at: textPosition, in: .forward)?[.attachment] as? NSTextAttachment { // Execute your attachment interaction logic here self.triggerAttachmentInteraction(for: attachment) return } // Fall back to default behavior for non-attachment taps super.touchesEnded(touches, with: event) } private func triggerAttachmentInteraction(for attachment: NSTextAttachment) { // Replace this with your actual interaction code—e.g., open a preview, navigate, etc. print("Tapped attachment: \(attachment)") // If you need to notify your view controller, you can use a delegate or closure here } }
Workaround 2: Add a UITapGestureRecognizer
If subclassing feels heavy-handed, you can attach a tap gesture recognizer to your existing UITextView and check for attachment taps that way. Just make sure to avoid interfering with the text view's default gestures:
// In your view controller's setup code (e.g., viewDidLoad) override func viewDidLoad() { super.viewDidLoad() let attachmentTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleAttachmentTap(_:))) // Allow the text view's default taps (like text selection) to still work attachmentTapGesture.cancelsTouchesInView = false textView.addGestureRecognizer(attachmentTapGesture) } @objc private func handleAttachmentTap(_ gesture: UITapGestureRecognizer) { let tapLocation = gesture.location(in: textView) guard let textPosition = textView.closestPosition(to: tapLocation) else { return } if let attachment = textView.textStyling(at: textPosition, in: .forward)?[.attachment] as? NSTextAttachment { // Run your interaction logic here self.handleAttachmentInteraction(attachment) } } private func handleAttachmentInteraction(_ attachment: NSTextAttachment) { // Your custom interaction code goes here }
Notes to Keep in Mind
- Both methods rely on
textStyling(at:in:)to detect attachments, which works reliably for most text attachment setups. - If you're using custom text attachments, make sure they conform to
NSTextAttachmentso the detection logic picks them up. - Once Apple releases a fix (hopefully in the next iOS update), you can remove this workaround code and revert to using the standard
textView(_:shouldInteractWith:in:interaction:)delegate method.
内容的提问来源于stack exchange,提问作者kukushi

