18

I asked a developer (TwoLivesLeft, the creators of Codea) how they did syntax highlighting in their app. He replied :

@TD2 the Codea editor is implemented using a UITextView. The highlighting is done by overlaying subviews in the appropriate positions — usually UILabels. They are dequeued from a re-use pool, similar to the way UITableViewCells work. During scrolling, the lines requiring re-highlighting pull markers out of the pool and lines that have moved off screen dump their markers back into the pool.

Can anyone explain how I would get the x and y of a certain word?

Allison
  • 2,213
  • 4
  • 32
  • 56
  • Here's how. https://discussions.apple.com/thread/2511930?start=0&tstart=0 –  Jul 14 '12 at 18:14

2 Answers2

42

UITextView conforms to UITextInput, of which a detailed description can be found here.

Take a look at the required methods "textRangeFromPosition:toPosition:", "positionFromPosition:offset:", "positionFromPosition:inDirection:offset:", and some of the other geometric-based methods in the UITextInput Protocol. Those might provide the functionality you are looking for.

I have not actually tried to make sure these work the way you want them too, but that looks like its about what you need.

Let me know if you need any more help!


UPDATE:

Here is some sample code of how to do this. I ended up getting the "firstRectForRange:" method to work. This code basically takes the last three letters of the UITextView "textStuff" and highlights it green.

UITextView *textStuff = [[UITextView alloc] init];
textStuff.frame = CGRectMake(2.0, 200.0, 200.0, 40.0);
textStuff.text = @"how are you today?";
textStuff.textColor = [UIColor blackColor];

UITextPosition *Pos2 = [textStuff positionFromPosition: textStuff.endOfDocument offset: nil];
UITextPosition *Pos1 = [textStuff positionFromPosition: textStuff.endOfDocument offset: -3];

UITextRange *range = [textStuff textRangeFromPosition:Pos1 toPosition:Pos2];

CGRect result1 = [textStuff firstRectForRange:(UITextRange *)range ];

NSLog(@"%f, %f", result1.origin.x, result1.origin.y);

UIView *view1 = [[UIView alloc] initWithFrame:result1];
view1.backgroundColor = [UIColor colorWithRed:0.2f green:0.5f blue:0.2f alpha:0.4f];
[textStuff addSubview:view1];

Result of running this code:

enter image description here

bddicken
  • 1,412
  • 1
  • 15
  • 16
  • Do you have an starting code that could give me something to push off of? – Allison Jul 15 '12 at 14:08
  • I updated the answer with some sample code. Start from there and modify it to make it work the way you want. – bddicken Jul 15 '12 at 22:08
  • Did this work for you? I would appreciate you to accept it as the answer if so. – bddicken Jul 17 '12 at 17:47
  • @bddicken It doesn't work if you put a line break after 'you' for instance. Not at iOS 7 / 8 – chrs Aug 19 '14 at 16:07
  • Hey @bddicken i am doing the same thing, but the textview is added on cell, so what is happening when the cell first appears it gives the rect but while reloading the cell this return me an infinite rect. Please do suggest to resolve this. My Q link is http://stackoverflow.com/questions/27288721/first-rect-returning-the-infinite-frame – Revinder Dec 05 '14 at 15:29
  • @chrs Solution for the \n newline problem http://stackoverflow.com/a/25983067/3549781 – iCanCode Jun 09 '15 at 13:06
6

@bddicken's https://stackoverflow.com/a/11487125/3549781 works like a charm. But the problem is, it doesn't work on iOS 7+ if the text contains a newline "\n". After a lot of searching I found a solution for that.

You have to ensure the layout of textView before calling firstRectForRange: by

[textView.layoutManager ensureLayoutForTextContainer:textView.textContainer];

Courtesy : UITextView firstRectForRange not working when there's new line characters in the mix

P.S : At first I added this as a comment to @bddicken's answer. As most people don't read comments I added this as an answer.

Community
  • 1
  • 1
iCanCode
  • 1,001
  • 1
  • 13
  • 24