Prior to Xcode 9 and iOS 11 I had a UITextView
within a UITableViewCell
that contained multiple links. Each link worked as expected, however since upgrading to iOS 11 and Xcode 9, the links no longer work.
The UITextView doesn't appear to recognise any touch interaction with func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool
never firing.
Has anyone else found this same problem after upgrading?
Turns out there wasn't a problem after all. Changes in the way UITextView responds to touches in iOS11 means that clicking links requires more of a press rather than just a tap which previously worked in iOS10. I think this may be something to do with the fact that in iOS11 you can now press links and drag them which also displays details of URL. So a firmer press is needed for the UITextView to register the link being tapped.
Specifically in iOS 11.0 and 11.1 (not later in 11.2+, not earlier in 10.x), textView(_:shouldInteractWith:in:interaction)
from UITextViewDelegate is called from an interaction with a UILongPressGestureRecognizer
instead of a UITapGestureRecognizer
.
For those two iOS versions, user needs a small delay long press instead of a tap for a native interaction with UITextView links.
If the callback doesn't get called at all for those two iOS versions, even on a long press, you've likely been messing with gesture recognizers by subclassing your UITextView and overriding gestureRecognizerShouldBegin(_)
to return false
when it shouldn't.
Here is an example of quick partial workaround for gestureRecognizerShouldBegin(_)
that will disable loupe/magnifier long press (if that's the desired intent of the override), but still allow long press on links:
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer is UIPanGestureRecognizer {
// required for compatibility with isScrollEnabled
return super.gestureRecognizerShouldBegin(gestureRecognizer)
}
if let tapGestureRecognizer = gestureRecognizer as? UITapGestureRecognizer,
tapGestureRecognizer.numberOfTapsRequired == 1 {
// allowing taps for links
return super.gestureRecognizerShouldBegin(gestureRecognizer)
}
if let longPressGestureRecognizer = gestureRecognizer as? UILongPressGestureRecognizer,
// allowing small delay long press for links (required for iOS 11.0-11.1)
// average comparison value is used to distinguish between:
// 0.12 (smallDelayRecognizer)
// 0.5 (textSelectionForce and textLoupe)
longPressGestureRecognizer.minimumPressDuration < 0.325 {
return super.gestureRecognizerShouldBegin(gestureRecognizer)
}
gestureRecognizer.isEnabled = false
return false
}
An alternative is to fully disallow both UILongPressGestureRecognizer
and UITapGestureRecognizer
except for a self-made UITapGestureRecognizer that you would have build yourself to interact with links.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With