In order to support the UIAccessibilityReadingContent
protocol, I need my UITextView to answer me questions about its lines. These are the methods of the protocol that I need to implement:
accessibilityLineNumberForPoint:
<- Provided a coordinate, return a line numberaccessibilityContentForLineNumber:
<- Return the text of a given lineaccessibilityFrameForLineNumber:
<- Given a line number, return its frameaccessibilityPageContent
<- The entire text content. That I have. :)
I figure that NSLayoutManager can help me, but I'm not that experienced with it. I've figured some of it out (I think), but still need some help.
Apple has some sample code (here) that can get me the number of lines in the text view:
NSLayoutManager *layoutManager = [textView layoutManager];
unsigned numberOfLines, index, numberOfGlyphs =
[layoutManager numberOfGlyphs];
NSRange lineRange;
for (numberOfLines = 0, index = 0; index < numberOfGlyphs; numberOfLines++){
(void) [layoutManager lineFragmentRectForGlyphAtIndex:index
effectiveRange:&lineRange];
index = NSMaxRange(lineRange);
}
I figure that with lineRange
above, I can calculate the line rects using this method on NSLayoutManager
:
- (NSRect)boundingRectForGlyphRange:(NSRange)glyphRange inTextContainer:(NSTextContainer *)container
And given lineRanges
I should be able to calculate the line number for a point using (by finding the lineRange
that contains the glyph index:
- (NSUInteger)glyphIndexForPoint:(CGPoint)point inTextContainer:(NSTextContainer *)container fractionOfDistanceThroughGlyph:(CGFloat *)partialFraction
So what remains is, how do I get the content of a line (as an NSString
), given a line number?
NSLayoutManager
offers methods that work with glyph ranges, as well as methods for characer ranges. Finally there are two methods that allow you to convert between both of those ranges :-[NSLayoutManager glyphRangeForCharacterRange:actualCharacterRange:]
and-[NSLayoutManager characterRangeForGlyphRange:actualGlyphRange:]
. To retrieve the string, simply convert the glyphRange you are interested in into a characterRange, then you can retrieve a substring from theUITextView
'stextStorage
usingattributedSubstringFromRange:
or bothstring
andsubstringWithRange:
. – Bindle