Animate NSLayoutManager drawing

1k views Asked by At

I have an NSLayoutManager which is drawing text using the following code:

[[self textLayoutManager] drawGlyphsForGlyphRange: NSMakeRange(0, [[self text] length])
                                          atPoint: textFrame.origin];    

in my view's -drawRect:. This works wonderfully, but what I'd really like to be able to do is animate the text in, character by character, as if it were being typed.

I've tried to append characters to a "visible string" variable, then call -[self setNeedsDisplay], but when dealing with text over approximately 20 characters, it begins to lag, as it redraws all of the text every time.

Regression: How can I animate NSLayoutManager's -drawGlyphsForGlyphRange:atPoint:?

1

There are 1 answers

0
zwaldowski On BEST ANSWER

(Disclaimer: I don't have a terrible lot of experience with the new APIs, so this is mostly coming from previous experience with text rendering.)

Your major slowdown is going to come from full-on changing the text the layout manager is working with. Even if you're just appending text, replacing the text it's using is going to cause it to throw out all its layout calculations - spacing, needed glyphs, actually reading those glyphs into RAM, applying attributes, etc. - and start over, which gets very expensive very quickly. In terms of actual NSLayoutManager, this is "invalidating the layout".

I see a couple of potential solutions off the top of my head. You could subclass NSLayoutManager ("You can create a subclass of NSLayoutManager to handle additional text attributes, whether inherent or not.") and override the showCGGlyphs:positions:count:font:matrix:attributes:inContext: to progressively ignore certain glyphs (thereby leaving the original text it's using intact). Another approach would be to emulate exactly what happens when you input text in a native container - use a mutable text storage, and append the desired text character-by-character, so that text calculation is done iteratively.

If those alone still don't have great performance, consider using those techniques in tandem with some of the native text views; although this is less true now than in past SDKs, a non-editable UITextView or a UILabel (for mutable and immutable text, respectively) contain far more optimizations than our mere mortal minds could comprehend.