2010-02-07 151 views

回答

29

您应该添加您的控制器的NSTextView[textView textStorage])的NSTextStorage对象的委托,然后实现委托方法‑textStorageDidProcessEditing:。这在文本更改时被调用。

在委托方法中,您需要使用-textStorage方法NSTextView从文本视图中获取当前的NSTextStorage对象。 NSTextStorageNSAttributedString的一个子类,包含视图的属性内容。

您的代码必须解析字符串并将着色应用到您感兴趣的任何文本范围。应用颜色的使用范围这样的事情,这将采用黄色整个字符串:

//get the range of the entire run of text 
NSRange area = NSMakeRange(0, [textStorage length]); 

//remove existing coloring 
[textStorage removeAttribute:NSForegroundColorAttributeName range:area]; 

//add new coloring 
[textStorage addAttribute:NSForegroundColorAttributeName 
        value:[NSColor yellowColor] 
        range:area]; 

你如何分析文本是由你。在解析文本时使用NSScanner是一个有用的类。

请注意,此方法绝不是处理语法着色的最有效方式。如果您正在编辑的文档非常大,您很可能会考虑将分析卸载到单独的线索和/或灵巧地重新分类文本的哪些部分。

+1

这有点旧了,但是如何实现'-textStorageDidProcessEditing:'到代理中? – Sirens 2012-07-23 15:53:57

+0

就像任何其他代表方法一样。查找[方法的签名](http://developer.apple.com/library/mac/documentation/cocoa/reference/NSTextStorageDelegate_Protocol/Reference/Reference.html#//apple_ref/doc/uid/TP40008627-CH1- DontLinkElementID_3)并将其放置在您的委托对象的实现中。确保你的委托对象被设置为'NSTextStorage'的委托。 – 2012-07-23 22:07:05

+0

谢谢,+1。你的方法比我的尝试更有效 – Sirens 2012-07-24 02:37:23

2

当然。你可以给NSTextView一个NSAttributedString,你可以用属性字符串做的一些事情是将颜色应用到字符串的某些子范围。

或者你可以search on Google看到很多人以前用过这个东西。

我可能会推荐使用OkudaKit

+1

它似乎OkudaKit不再在开发 – Stephan 2012-12-12 05:47:43

4

我建议你通过阅读CocoaDev page有关语法Highlighing启动。很多人都有针对不同目标的解决方案。

如果您想要执行源代码语法高亮显示,我建议您查看Uli KustererUKSyntaxColoredTextDocument

+0

大声笑,从来没有从1个单一网站下载这么多样本,太棒了! – 2011-07-26 20:01:56

+0

提到的工具现在在github上:[UKSyntaxColoredTextDocument](https://github.com/uliwitness/UKSyntaxColoredTextDocument) – Stephan 2012-12-12 05:54:47

9

Rob Keniger's answer是好的,但对于某人来说找一个更具体的例子,这里是一个简短的语法高亮显示我写的应该突出的正则表达式的模板语法。我想\是灰色的,随着字符紧跟着它们变成黑色。我想$是红色的,紧接在$之后的数字字符也是红色的。其他一切应该是黑色的。这里是我的解决方案:

我做了一个模板荧光笔类,它有一个头,看起来像这样:

@interface RMETemplateHighlighter : NSObject <NSTextStorageDelegate> 

@end 

我初始化它的笔尖文件作为一个对象,并把它挂到我的一个视图控制器出口。在视图控制器的awakeFromNib,我有这个(其中replacer是我NSTextView出口和​​是上述类出口):

self.replacer.textStorage.delegate = self.templateHighlighter; 

,我的实是这样的:

- (void)textStorageDidProcessEditing:(NSNotification *)notification { 
    NSTextStorage *textStorage = notification.object; 
    NSString *string = textStorage.string; 
    NSUInteger n = string.length; 
    [textStorage removeAttribute:NSForegroundColorAttributeName range:NSMakeRange(0, n)]; 
    for (NSUInteger i = 0; i < n; i++) { 
     unichar c = [string characterAtIndex:i]; 
     if (c == '\\') { 
      [textStorage addAttribute:NSForegroundColorAttributeName value:[NSColor lightGrayColor] range:NSMakeRange(i, 1)]; 
      i++; 
     } else if (c == '$') { 
      NSUInteger l = ((i < n - 1) && isdigit([string characterAtIndex:i+1])) ? 2 : 1; 
      [textStorage addAttribute:NSForegroundColorAttributeName value:[NSColor redColor] range:NSMakeRange(i, l)]; 
      i++; 
     } 
    } 
} 

所以你去了,一个充分运作的例子。有几个细节让我绊倒了大约10分钟,比如你必须从textStorage中取出字符串才能访问各个角色...也许这会在几分钟内保存其他人。

+0

谢谢,作品广告和保存我相当一段时间。 – 2014-05-09 18:19:33

+0

这对于语法高亮显得很好,但在我的情况下,似乎也打破了我的UITextView的'contentSize'。更具体地说,'contentSize'似乎总是UITextView的宽度x单行高度。 – carloe 2015-05-07 11:53:43

+0

@carloe:这是一个OS X解决方案...你提到'UITextView'(不是NS **'TextView'),所以我假设你正在使用iOS。这些API之间可能存在细微差异...... OS X上最好的版本在iOS上可能不是最好的。 – ArtOfWarfare 2015-05-07 14:34:33