I just wanted to add Ramshad's answer on how to deal with a valid frame.
To do this, you may need to use UITextView instead of UILabel, which does not give you access to how it controls the layout of the text. By disabling editing, selection, and scrolling, a UITextView behaves in much the same way as a UILabel, with the exception of some additions that you have to remove.
For convenience, you can add a small category to the UITextView in which you write a method to check whether a point touches any of the characters in the range.
- (BOOL)point:(CGPoint)point touchesSomeCharacterInRange:(NSRange)range { NSRange glyphRange = [self.layoutManager glyphRangeForCharacterRange:range actualCharacterRange:NULL]; BOOL touches = NO; for (NSUInteger index = glyphRange.location; index < glyphRange.location + glyphRange.length; index++) { CGRect rectForGlyphInContainer = [self.layoutManager boundingRectForGlyphRange:NSMakeRange(index, 1) inTextContainer:self.textContainer]; CGRect rectForGlyphInTextView = CGRectOffset(rectForGlyphInContainer, self.textContainerInset.left, self.textContainerInset.top); if (CGRectContainsPoint(rectForGlyphInTextView, point)) { touches = YES; break; } } return touches; }
This will also work for a piece of text containing several words spreading over several lines due to word wrap. He will also work on localized texts as we deal with printed glyphs.
source share