How to clear a UITextView with a custom NSTextStorage? [iOS7 only]

3k Views Asked by At

I'm currently trying to create an SMS-like screen, where the user can write some text and send it to other users. Everything goes as expected until I try to clear my text view and encounters a crash. I've been trying to find a way around this issue, but I just cannot find enough documentation online. So here it is, and hopefully one of you will know a fix for this.


The implementation

My UITextView is a subclass of Peter Steinberger's implementation for iOS7, and I use it with a custom NSTextStorage subclassed as showed in objc.io's 'Getting to Know TextKit' and especially that source code in order to highlight usernames in the message.

In my ViewController, I configure my text storage like this:

self.textStorage = [[[MyCustomTextStorage alloc] init] autorelease]; [self.textStorage addLayoutManager:self.textView.layoutManager];

And then in my TextView's delegate method:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text

I store the input in my custom TextStorage:

[self.textStorage.string stringByReplacingCharactersInRange:range withString:text];

The crash

I can retrieve my text via self.textStorage.string, and then I clear my text view by replacing characters in the range of the input string. This works quite well, but when I try to set my TextView as the first responder again, the application crashes.

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSCFString _getBlockStart:end:contentsEnd:forRange:stopAtLineSeparators:]: Range {5, 0} out of bounds; string length 0'

The range mentioned is the range of my previously cleared string so it looks like I can clear the display, but my TextStorage / TextView is keeping a reference to the first edited range / string.


Any idea on what could be causing this crash and how to resolve it? Thanks for your attention; at this point any help is appreciated, so please feel free to post if you have some piece of advice. :)

3

There are 3 best solutions below

2
On

The reason it's crashing is because you are using a range that it outside the bounds of the string in the textStorage. If you want to clear the textView why not just use self.textStorage.string=@""

0
On

After replacing text, try:

[self setSelectedRange:NSMakeRange(0, 0)];
0
On

Same situation with you.

It costed me half a day to solve it.

  1. The example you provide is right.

  2. Your app will crash not only when you are clearing it, but also when using -setText: every time.

  3. They don't crash beacause they would never call -setText:!!!

Solution:

add all TextKit staffs you need to your code,

like this:

_textStorage = [[NSTextStorage alloc] init];
_layoutManager = [[NSLayoutManager alloc] init];
[_textStorage addLayoutManager:_layoutManager];
_textContainer = [[NSTextContainer alloc] init];
[_layoutManager addTextContainer:_textContainer];
_myTextView = [[UITextView alloc] initWithFrame:frame textContainer:_textContainer];

Actually, you missed the NSTextContainer, so there's no right container for string to put in, then the app crashed.

Maybe you can send pull requests to these two demo project, for not miss leading other people.