title: How to highlight CoreText with changing highlight colors?
body: <p>I have a subclass of UIView that implements code to draw CoreText.  In the application, that UIView is drawn inside a UIScrollView.  Here is the code that I currently use in drawRect: to render an NSAttributedString:</p>
  
  <pre><code>CGContextRef context = UIGraphicsGetCurrentContext();
  
  float viewHeight = self.bounds.size.height;
  CGContextTranslateCTM(context, 0, viewHeight);
  CGContextScaleCTM(context, 1.0, -1.0);
  CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1.0, 1.0));
  
  CGMutablePathRef path = CGPathCreateMutable();
  CGRect bounds = CGRectMake(PADDING_LEFT, -PADDING_TOP, self.bounds.size.width-20.0, self.bounds.size.height);
  CGPathAddRect(path, NULL, bounds);
  
  CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFMutableAttributedStringRef)attrString);
  CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
  CFRelease(framesetter);
  CFRelease(path);
  CTFrameDraw(frame, context);
  </code></pre>
  
  <p>In my NSAttributedString, I have certain text attributes to color the text.</p>
  
  <p>What I need help with is conceptually, how should this be accomplished?  I am confused by all the various methods of drawing frames, layers, etc.  I have tried to review several books and other resources, but I feel like I'm missing some basic stuff.</p>
  
  <p>Here are my requirements:</p>
  
  <ol>
  <li>Highlights obviously need to be redrawn to the new location on a change of orientation.</li>
  <li>Highlight color needs to be able to be changed programmatically on an individual highlight basis.</li>
  <li>Ideally for performance, I don't want to have to re-draw the entire CoreText UIView when I just change the highlight color of one highlight.</li>
  <li>The individual Rects must be able to be grouped together to form a single highlight since highlights can cover a range that goes beyond a single CTLine.</li>
  <li>Eventually, I want to implement UIMenuController on CoreText view so I believe that the highlights must be drawn underneath the CoreText UIView?</li>
  </ol>
  
  <p>I would greatly appreciate any assistance.</p>
  
  <p>Here is what I have tried so far:</p>
  
  <p>I added a new UIView as a subview to the UIScrollView to contain the highlights.  I then add individual UIViews for the highlights themselves.  When I create dummy "test" highlights, they appear correctly under the CoreText view.  I can also easily change the highlight color.  However, when I go to acquire actual information about the lines from the CoreText view to create real highlights, it returns zero lines.  Could this be because drawRect isn't finished drawing yet or something else?</p>
  
  <p>Here are some questions:</p>
  
  <ol>
  <li>Should I add a UIView as a subview to the UIScrollView to contain all the highlights with additional subviews for each individual highlight?  Then, store each highlight UIView in a nested NSArray?</li>
  <li>If I change the color of a highlight beneath the CoreText UIView, will that cause the entire UIView to be redrawn?  If so, how can I design around this?</li>
  <li>It is true that if I want the CoreText UIView to receive the input for UIMenuController, that I have to place the highlight objects beneath the CoreText UIView?</li>
  </ol>
  
  <p>I have seen this open source project:</p>
  
  <p><a href="https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML" rel="nofollow noreferrer">https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML</a></p>
  
  <p>This is amazing what it can do, but is far more complex and detailed than I need.  The code renders each individual glyph run using CoreText and permits highlighting, which is awesome.  However, I am trying to keep my code simple and lightweight.  I know very little about CoreGraphics, CoreAnimation or CoreText.</p>
  
  <p>I have also seen this question:</p>
  
  <p><a href="https://stackoverflow.com/questions/4477742/core-text-get-pixel-coordinates-from-nsrange">Core Text - Get Pixel Coordinates from NSRange</a></p>
  
  <p>The answer to the question provides the calls to determine the bounds of a Rect for a given range in a given line.  I think I can figure out those calls.</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>Here is what I have done now.  I'm sure this is wrong, but it is the only way I could find to make it work...</p>
  
  <ol>
  <li>Create a UIView as a container to add to the UIScrollView as a subview.</li>
  <li>Pass UIView to CoreTextView.  I also pass an array of string ranges to CoreTextView to indicate which strings should be highlighted.</li>
  <li>Add CoreTextView as a subview of UIScrollView.  That way, UIView is underneath CoreTextView.</li>
  <li>In the drawRect: function of CoreTextView, I draw the CoreText.  I then call a function to calculate the highlights.</li>
  <li>Each NSRange is checked against the lines and the CGRect of each match in the line is calculated.</li>
  <li>CGRect is used to create a new UIView.  That UIView is added as a subView of the UIView container.  It is also added to an NSArray so that I can keep track of it and change the highlight color of an individual highlight as needed.</li>
  </ol>
  
  <p>This does not call drawRect each time a highlight is added to the container or color changed.  However, I know this isn't an ideal solution.  Problems with this solution:</p>
  
  <ol>
  <li>When the UIViewController calls setNeedsDisplay on the CoreTextView, there is no way to know when it is done drawing.  I still can't find a way to do a callback to tell the ViewController that it is okay to proceed with the next task.</li>
  <li>By adding UIViews to the other container UIView, drawRect is technically drawing items outside of its own rect, which I know is a no no.</li>
  <li>I'm sure this isn't the most performant way of doing this, although it does seem to work pretty well.</li>
  </ol>