iosobjective-ctextkitnstextcontainer

NSTextContainer exclusionPaths freezes app and uses 99% CPU on iOS 7.1 - workaround?


I'm trying to exclude a square in a UITextView using NSTextContainer's excludePaths, like so:

NSTextStorage* textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString];
NSLayoutManager *layoutManager = [NSLayoutManager new];
[textStorage addLayoutManager:layoutManager];

NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:self.bounds.size];

UIBezierPath *rectanglePath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 250, 250)];
textContainer.exclusionPaths = @[rectanglePath];

[layoutManager addTextContainer:textContainer];

self.textView = [[UITextView alloc] initWithFrame:self.bounds textContainer:textContainer];
self.textView.editable = NO;
self.textView.scrollEnabled = NO;
[self addSubview:self.textView];

This works fine in iOS 7.0:

with iOS 7.0

In iOS 7.1, however, this will result in an infinite loop somewhere in lineFragmentRectForProposedRect:atIndex:writingDirection:remainingRect: of NSTextContainer, using 99% CPU and leaking memory like crazy. The app is completely unresponsive and is eventually terminated due to memory use. Apparently this is a bug in iOS 7.1.

When I change the x-origin of the exclusion rectangle by just one point (origin to {1,0}), it works, but looks terrible:

with iOS 7.1 and one point to the right

The bug only seems to happen when the first character of the first line is affected by the exclusion rect. When I change the exclusion rect to {0,30}, it will also work:

iOS 7.1 and 0,30

But obviously this is not what I want. Does anyone know how I can work around this bug?


Solution

  • I have the same issue, to fix this i placed:

    mytextView.exclusionPaths = @[rectanglePath] 
    

    into layoutSubview method. I hope this will help someone