如果突出显示的单词是一行的第一个,则 textView 中的 NSBackgroundColorAttributeName 不考虑范围

NSBackgroundColorAttributeName in textView doesn't respect range if highlighted word is first of a line

我正在实施 "search in chat" 功能,我希望搜索到的词在消息中突出显示。如标题所述,问题是如果单词是一行的第一行(长消息显然 multi-line),则整行而不是单个单词被突出显示。

调试的时候,我也试过用下划线代替backgroundcolor,下划线是正确的。我不知道问题出在哪里。 我的应用程序的聊天是基于 JSQMessagesViewController 所以我认为问题可能出在这里。

[attributedString addAttribute:NSBackgroundColorAttributeName
                         value:backColor
                         range:wordRange];
[attributedString addAttribute:NSUnderlineStyleAttributeName
                         value:@(NSUnderlineStyleSingle)
                         range:wordRange];

cell.textView.attributedText = attributedString;

我没有post计算范围的代码,因为范围是正确的;事实上,如果我在调试中查看 attributedString 的预览(我将其分配给 cell.textView.attributedText),我可以看到只有单词被突出显示,而不是所有字符串。

这是一个例子:

似乎是系统框架中的错误,所以最好的办法可能是再添加一行代码,将背景颜色设置回 "unchanged",紧接在应该更改背景的最后一个字符之后。 祝你好运!

看了official documentation后,我发现有3个方法做类似的动作。

  1. setAttributes:range:
  2. addAttribute:value:range:
  3. addAttributes:range:

因此,可能还有其他方法,例如 setAttributes:range:,可能会解决您的问题。

[attributedString setAttributes:@{NSBackgroundColorAttributeName : backColor}
                          range:wordRange];

cell.textView.attributedText = attributedString;

另外,Whosebug上也有类似的问题。也许 this answer 会对你有所帮助。

NSDictionary *stringAttributes = [NSDictionary dictionaryWithObject:(id)backColor.CGColor
                                                             forKey:(id)kCTBackgroundColorAttributeName];
[attributedString addAttributes:stringAttributes 
                          range:wordRange];

cell.textView.attributedText = attributedString;

更新#1

刚刚找到 Attributed String Programming Guide.
它说,

All of the methods for changing a mutable attributed string properly update the mapping between characters and attributes, but after a change some inconsistencies can develop.

或许,以上原因导致了您的问题... 我不确定它是否有帮助,但有一个例子:

NSMutableAttributedString *string; // assume string exists
NSRange selectedRange; // assume this is set

NSURL *linkURL = [NSURL URLWithString:@"http://www.apple.com/"];

[string beginEditing]; // ★★★ Apple uses beginEditing ★★★
[string addAttribute:NSLinkAttributeName
               value:linkURL
               range:selectedRange]; 
[string addAttribute:NSForegroundColorAttributeName
               value:[NSColor blueColor]
               range:selectedRange];
[string addAttribute:NSUnderlineStyleAttributeName
               value:[NSNumber numberWithInt:NSSingleUnderlineStyle]
               range:selectedRange];
[string endEditing]; // ★★★ and endEditing ★★★