开发者

Cocoa (Snow Leopard) NSTextView's textStorage -setAttributes:range: removes characters!

开发者 https://www.devze.com 2023-01-21 01:28 出处:网络
I\'m not sure what I\'m doing wrong.I have a NSTextView and am registered as the delegate for its textStorage attribute.When I receive -textStorageDidProcessEditing:notification: I\'m trying to apply

I'm not sure what I'm doing wrong. I have a NSTextView and am registered as the delegate for its textStorage attribute. When I receive -textStorageDidProcessEditing:notification: I'm trying to apply attributes to ranges of characters within the text. It certainly does "something" to the characters, but not what I expect... they just disappear!

A heavily distilled code example. This should make sure the second character in the text field is always red:

-(void)textStorageDidProcessEditing:(NSNotification *)notification {
  NSTextStorage *textStorage = [textView textStorage];
  if ([[textStorage string] length] > 1) {
    NSColor *color = [NSColor redColor];
    NSDictionary *attributes = [NSDictionary dictionaryWit开发者_Python百科hObjectsAndKeys:color, NSForegroundColorAttributeName, nil];
    [textStorage setAttributes:attributes range:NSMakeRange(1, 1)];
  }
}

Instead, as I type the sequence "abcdefg" I get "a", then when I hit "b" seemingly nothing happens, then when I hit "cdefg" typing occurs as normal, making the end result "acdefg"... the "b" is missing!

If I start hitting backspace I have to hit backspace 7 times, as if the "b" is actually there, but just not being drawn (cursor stalls as it deletes the "b", then on the next backspace deletes the "a" as expected).

If I apply attributes to some default text in the view using the same -setAttributes:range: method before the view is drawn then it does exactly as I expect.

Any clues? It seems like a fairly normal use of a NSTextStorageDelegate :)

I've tried calling -setNeedsDisplay on the text field to no avail.


Figured it out. Using NSTextStorage's -addAttribute:value:range works. I still don't fully understand why but at least I can get over it and move on.

-(void)textStorageDidProcessEditing:(NSNotification *)notification {
  // ... SNIP ...
  [textStorage addAttribute:NSForegroundColorAttributeName
                      value:[NSColor redColor]
                      range:NSMakeRange(1, 1)];
}

Makes the code a bit less cluttered too.


I'm not sure how relevant this is for you after so many years but I think the reason for it was that you were setting attributes with a dictionary which does not contain NSFontAttributeName, effectively removing it from the textview.

So I think this should work:

-(void)textStorageDidProcessEditing:(NSNotification *)notification {
  NSTextStorage *textStorage = [textView textStorage];
  if ([[textStorage string] length] > 1) {
    NSColor *color = [NSColor redColor];
    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:color, NSForegroundColorAttributeName, [NSFont ...whatever...], NSFontAttributeName, nil];
    [textStorage setAttributes:attributes range:NSMakeRange(1, 1)];
  }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消