Getting the word touched in a UILabel/UITextView

(There is a link to a sample code project in your linked post that does contain some useful sample code, but I will outline the process for you here too.)

In short, you are going to need to use Core Text, which is Apple’s advanced C-based text handling framework that backs all sophisticated text layout in iOS and OS X.

The full code is going to be somewhat involved, but key methods you are going to want to look at are:

CTFramesetterCreateWithAttributedString() – use this, in conjunction with an NSAttributedString that you will get from your label’s text – to create the framesetter

CTFramesetterCreateFrame() – use this to get a CTFrameRef for your text from the above framesetter. You will need to create a CGPathRef using your label bounds to do this.

CTFrameGetLines(), CTFrameGetLineOrigins() – use these to get CTLineRefs corresponding to the typeset lines, and the coordinates of the line origins, respectively, then use CTLineGetStringIndexForPosition() to find the character index at a touch location.

You can then use this character index (in the line’s reference frame) to work backward and find the actual character/word/etc within your full string.

Don’t forget that matters are complicated by a couple issues:

  1. If you use UILabel’s native drawing you will have to take care to perfectly match your typesetting metrics, which can be cumbersome since most of the objects (e.g. CTFontRef) are not toll-free bridged with their UIKit counterparts. Implementing your own drawing may, sometimes, be easier, which will guarantee metric matching.

  2. Core Text uses an inverted coordinate system with respect to the normal iOS drawing system. If you are getting wacky results, and especially if you do your own drawing, this is something to take a look at.

Not the easiest task in the world, but far from impossible. Good luck!

Leave a Comment