TextKit + iOS Clipping Bug

I’ve just spent several hours hunting an iOS 8 specific bug. After inserting several new lines into a UITextView (with custom TextKit stack), the newly-added text would not appear.

This is the way our NSTextContainer instance was being initialized

[cc lang=”objc”]
@implementation MyTextView
– (instancetype)init {
SPInteractiveTextStorage *textStorage = [[MyInteractiveTextStorage alloc] init];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];

NSTextContainer *container = [[NSTextContainer alloc] initWithSize:CGSizeMake(0, CGFLOAT_MAX)];
container.widthTracksTextView = YES;
container.heightTracksTextView = YES;

[layoutManager addTextContainer:container];
[textStorage addLayoutManager:layoutManager];

self = [super initWithFrame:CGRectZero textContainer:container];
// …
[/cc]

Now, the interesting part is, specifically, heightTracksTextView = YES.

After several debugging hours, i figured out that iOS 7 was setting, by default heightTracksTextView to NO, after setting the UITextView’s scrollEnabled property.

Guess what? that’s different in iOS 8. Calling setScrollEnabled is not backfiring anymore. For some reason, if you just disable heightTracksTextView, and initialize your UITextView instance with that custom NSTextContainer, any call to the caretRectForPosition method will fail.

By that, i mean, caretRectForPosition will return an invalid position. Workaround? manually disabling heightTracksTextView, right after calling the super initialized.

By the way, for future reference, this post and this one helped me understand i wasn’t alone in Mordor.

%d