UITextView 属性文本和语法突出显示

标签 uitextview syntax-highlighting ios6 nsattributedstring uitextviewdelegate

背景

因此,在 iOS 6 中,UITextView 可以采用属性字符串,这对于语法突出显示可能很有用。

我正在 -textView:shouldChangeTextInRange:replacementText: 中执行一些正则表达式模式,并且经常需要更改已输入单词的颜色。除了重置属性文本之外,我没有看到其他选项,这需要时间。

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    //A context will allow us to not call -attributedText on the textView, which is slow.
    //Keep context up to date
    [self.context replaceCharactersInRange:range withAttributedString:[[NSAttributedString alloc] initWithString:text attributes:self.textView.typingAttributes]];

    // […]

    self.textView.scrollEnabled = FALSE;

    [self.context setAttributes:self.defaultStyle range:NSMakeRange(0, self.context.length)];
    [self refresh]; //Runs regex-patterns in the context
    textView.attributedText = self.context;

    self.textView.selectedRange = NSMakeRange(range.location + text.length, 0);
    self.textView.scrollEnabled = TRUE;

    return FALSE;
}

这在模拟器上运行还不错,但在 iPad 3 上,每个 -setAttributedText 需要几百毫秒。

我向 Apple 提交了一个错误,请求能够改变 attributeText。它被标记为重复,所以我看不到他们对此有何评论。

问题

更具体的问题: 如何更改 UITextView 中某些范围的颜色(带有大的彩色文本),并且性能足够好,可以在每个 shouldReplaceText... 中执行此操作?

更广泛的问题: 如何在 iOS 6 中使用 UITextView 进行语法突出显示?

最佳答案

我在我的应用程序 Zap-Guitar(无弦乐)中遇到了同样的问题,我允许用户输入/粘贴/编辑他们自己的歌曲,并且应用程序会突出显示已识别的和弦。

是的,苹果使用 html 编写器和解析器来显示属性文本。幕后的精彩解释可以在这里找到:http://www.cocoanetics.com/2012/12/uitextview-caught-with-trousers-down/

我发现这个问题的唯一解决方案是不使用属性文本,这对于语法突出显示来说是一种过度的杀伤力。

相反,我恢复了带有纯文本的旧版 UITextView,并在需要突出显示的 TextView 中添加了按钮。为了计算按钮框架,我使用了这个答案:How to find position or get rect of any word in textview and place buttons over that?

这将 CPU 使用率降低了 30%(或多或少)。

这是一个方便的类别:

@implementation UITextView (WithButtons)
- (CGRect)frameForTextRange:(NSRange)range {
    UITextPosition *beginning = self.beginningOfDocument;
    UITextPosition *start = [self positionFromPosition:beginning offset:range.location];
    UITextPosition *end = [self positionFromPosition:start offset:range.length];
    UITextRange *textRange = [self textRangeFromPosition:start toPosition:end];
    CGRect rect = [self firstRectForRange:textRange];
    return [self convertRect:rect fromView:self.textInputView];
}

@end

关于UITextView 属性文本和语法突出显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12543468/

相关文章:

ios6 - iPhone 应用程序后台的 GPS 位置更新

xcode - UITextView 的指定初始化器

syntax-highlighting - D 的 Nano 语法高亮规则

vim - 将 vim GUI 配色方案转换为使用 256 色 vim 的自动方法?

Vim 不正确地突出显示 "very magic"和 "very nomagic"正则表达式

ios - 从调试器打印时,为什么有些字典键有引号而有些没有?

YouTube 嵌入式视频的 iOS 6.0+ 自动旋转

iphone - 如果用户输入 "",UITextView 文本属性返回 " "?

ios - UITextView 不更改 textColor 属性

ios - UITableView beginUpdates endUpdates 使行闪烁