As you mentioned, textView:shouldInteractWithTextAttachment:inRange:
is not meant to work for editable text views. A way around this is to implement your own UITapGestureRecognizer
and do something like this:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
if (self.state == UIGestureRecognizerStateFailed) return;
UITouch *touch = [touches anyObject];
UITextView *textView = (UITextView*) self.view;
NSTextContainer *textContainer = textView.textContainer;
NSLayoutManager *layoutManager = textView.layoutManager;
CGPoint point = [touch locationInView:textView];
point.x -= textView.textContainerInset.left;
point.y -= textView.textContainerInset.top;
NSUInteger characterIndex = [layoutManager characterIndexForPoint:point inTextContainer:textContainer fractionOfDistanceBetweenInsertionPoints:nil];
if (characterIndex >= textView.text.length)
{
self.state = UIGestureRecognizerStateFailed;
return;
}
_textAttachment = [textView.attributedText attribute:NSAttachmentAttributeName atIndex:characterIndex effectiveRange:&_range];
if (_textAttachment)
{
return;
}
_textAttachment = nil;
}
Then you add this gesture recogniser to your text view and when the gesture is recognized you ask for the _textAttachment
value.
Bear in mind that characterIndexForPoint:inTextContainer: fractionOfDistanceBetweenInsertionPoints:
returns the nearest character index. You might want to check if the point is inside the attachment depending on what you're planning to do.