thinking in an easy solution, here is a small code that reproduce what you need
- (void)analyse:(UITextView *)textView
{
NSLayoutManager *layoutManager = [textView layoutManager];
NSString *string = textView.text;
unsigned numberOfLines, index, stringLength = [string length];
NSMutableArray *ranges = [NSMutableArray new];
NSMutableArray *frames = [NSMutableArray new];
for (index = 0, numberOfLines = 0; index < stringLength; numberOfLines++)
{
NSRange tmprange;
NSRange range = [string lineRangeForRange:NSMakeRange(index, 0)];
CGRect rect = [layoutManager lineFragmentRectForGlyphAtIndex:index
effectiveRange:&tmprange];
[ranges addObject:[NSValue valueWithRange:range]];
[frames addObject:[NSValue valueWithCGRect:rect]];
index = NSMaxRange(tmpRange);
}
self.ranges = ranges;
self.frames = frames;
self.numberOfLines = numberOfLines;
}
Please take a look of the properties:
self.ranges = ranges;
self.frames = frames;
self.numberOfLines = numberOfLines;
You can have the following in your class to create this properties:
@property (nonatomic) NSInteger numberOfLines;
@property (strong, nonatomic) NSArray *ranges;
@property (strong, nonatomic) NSArray *frames;
I suggest you to add the analyse call inside the following delegate:
- (void)textViewDidChange:(UITextView *)textView
There you can for example after analyse get the frame of the 2nd line just doing: self.frames[1]
Or getting the text of the second line doing: [textView.text substringWithRange:[self.ranges[1] rangeValue]]
For example like this:
if (self.numberOfLines > 1)
{
NSRange range = [self.ranges[1] rangeValue];
NSLog(@"2nd line = %@", [textView.text substringWithRange:range]);
NSLog(@"2nd line frame = %@", self.frames[1]);
}
Having all the frames in self.frames I think you can easily do the other thing, guess the line number using a coordinate.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…