简体   繁体   English

如何使用自定义NSTextStorage清除UITextView? [仅限iOS7]

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

I'm currently trying to create an SMS-like screen, where the user can write some text and send it to other users. 我目前正在尝试创建一个类似于SMS的屏幕,用户可以在其中写一些文本并将其发送给其他用户。 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. 我的UITextView是Peter Steinberger对iOS7的实现的子类,我将其与自定义NSTextStorage子类一起使用,如objc.io的“ Getting to Know TextKit”(尤其是该源代码)中所示,以突出显示消息中的用户名。

In my ViewController, I configure my text storage like this: 在ViewController中,我像这样配置文本存储:

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

And then in my TextView's delegate method: 然后在我的TextView的委托方法中:

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

I store the input in my custom TextStorage: 我将输入存储在自定义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. 我可以通过self.textStorage.string检索文本,然后通过替换输入字符串范围内的字符来清除文本视图。 This works quite well, but when I try to set my TextView as the first responder again, the application crashes. 这工作得很好,但是当我尝试再次将TextView设置为第一响应者时,应用程序崩溃。

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. 提到的范围是我先前清除的字符串的范围,因此看起来我可以清除显示,但是我的TextStorage / TextView保留对第一个已编辑范围/字符串的引用。


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. 此时,我们将为您提供任何帮助,因此,如果有任何建议,请随时发表。 :) :)

The reason it's crashing is because you are using a range that it outside the bounds of the string in the textStorage. 崩溃的原因是因为您使用的范围超出了textStorage中字符串的范围。 If you want to clear the textView why not just use self.textStorage.string=@"" 如果要清除textView,为什么不只使用self.textStorage.string = @“”

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. 您的应用程序不仅会在清除时崩溃,还会在每次使用-setText:-setText:

  3. They don't crash beacause they would never call -setText: !!! 他们不会崩溃,因为他们永远不会打电话给-setText: !!!

Solution: 解:

add all TextKit staffs you need to your code, 将您需要的所有TextKit人员添加到代码中,

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. 实际上,您错过了NSTextContainer ,因此没有合适的容器可放入字符串,然后应用程序崩溃了。

Maybe you can send pull requests to these two demo project, for not miss leading other people. 也许您可以将拉取请求发送到这两个演示项目,以免错过领导他人。

替换文字后,请尝试:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM