iosobjective-ctextkitnslayoutmanagernstextstorage

Invalid glyph index when setting viewController's layoutManager for NSTextStorage subclass


My goal is to use TextKit to italicize, set the text size, etc. of certain words.

To start, I am only trying to highlight a character in my text string. Being new to TextKit (and truthfully to programming in general), I am following the syntax highlighting topic of obc.io issue #5.

When using the NSLayoutManager built-in to the UITextView I created, my text appears on screen with no thrown exceptions. When I set my UITextView as the layout manager of my NSTextStorage subclass in my view controller (below), I receive errors for an exception for invalid glyph index(s).

_textStorage = [BBRSyntaxHighlightTextStorage new]; 
[_textStorage addLayoutManager: self.readerTextView.layoutManager];

The console output is below:

_NSLayoutTreeLineFragmentRectForGlyphAtIndex invalid glyph index 528
2013-12-01 15:23:24.949 BibleReader[6077:70b] !!! _NSGlyphTreeInvalidateGlyphsForCharacterRange invalid char range 1
2013-12-01 15:23:24.956 BibleReader[6077:70b] !!! _NSLayoutTreeLineFragmentRectForGlyphAtIndex invalid glyph index 528
2013-12-01 15:23:24.957 BibleReader[6077:70b] !!! _NSGlyphTreeInvalidateGlyphsForCharacterRange invalid char range 1
2013-12-01 15:23:24.957 BibleReader[6077:70b] !!! _NSGlyphTreeInvalidateGlyphsForCharacterRange character count mismatch
2013-12-01 15:23:24.958 BibleReader[6077:70b] !!! _NSLayoutTreeLineFragmentRectForGlyphAtIndex invalid glyph index 4040
2013-12-01 15:23:24.959 BibleReader[6077:70b] !!! _NSGlyphTreeInvalidateGlyphsForCharacterRange invalid char range 1

I have read through Apple's Text Programming Guide many times and think I understand how the text system is established, but have no idea why my glyph count would exceed the number of glyphs...

I created gist's for my viewController and NSTextStorage subclass, here and here, respectively.


Solution

  • It looks like your layout manager hasn't been properly removed from its original NSTextStorage object. Call [self.readerTextView.textStorage removeLayoutManager:self.readerTextView.layoutManager] before you add the layout manager to your custom text storage sub class.

    In general, I've found TextKit to not play well when mixing nib/xib/storyboard created UITextViews with custom subclasses of the TextKit objects. You can get around some of this by overriding - (id)awakeAfterUsingCoder:(NSCoder *)aDecoder on UITextView and constructing the text system using the classes you want, but normally I'd recommend sticking to in-code custom text system creation.