删除NSTextView文本选择的属性

时间:2016-01-03 13:01:00

标签: cocoa nsattributedstring nstextview nsrange

我有一个通过界面构建​​器添加的NSTextView对象。我可以更改已选择的文本段的背景颜色,如下所示。

- (void)emphasizeText {
    NSColor *c = [colorWell.color colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; //colorWell is an NSColorWell object that has been added through interface builder
    NSRange selection = textView1.selectedRange; //textView1 is an NSTextView object that has been added through interface builder
    [textView1.textStorage addAttributes:@{NSBackgroundColorAttributeName:c} range:selection];
}

然而,我无法从所选文本段中删除添加的属性(NSBackgroundColorAttributeName)。在参考this topic时,我有以下代码。

- (void)deemphasizeText {
    NSMutableAttributedString *aStr = [textView1.attributedString mutableCopy];
    NSRange selection = textView1.selectedRange;
    [aStr enumerateAttribute:NSBackgroundColorAttributeName inRange:selection options:0 usingBlock:^(id value,NSRange range,BOOL *stop) {
        if (value) {
            [aStr removeAttribute:NSBackgroundColorAttributeName range:range];
        }
    }];
}

虽然应用程序不会崩溃,但没有任何变化。我做了几个变种,比如

- (void)deemphasizeText {
    NSRange selection = textView1.selectedRange;
    NSMutableAttributedString *aStr = [[NSMutableAttributedString alloc] initWithAttributedString:(NSMutableAttributedString *)[textView1.textStorage attributedSubstringFromRange:selection]];
    [aStr enumerateAttribute:NSBackgroundColorAttributeName inRange:NSMakeRange(0,aStr.length) options:0 usingBlock:^(id value,NSRange range,BOOL *stop) {
        if (value) {
            [aStr removeAttribute:NSBackgroundColorAttributeName range:range];
        }
    }];
}

同样,所选片段不会改变。我做错了什么?

Muchos thankos。

1 个答案:

答案 0 :(得分:0)

首先,您的-deemphasizeText方法明确使用文本存储可变字符串的副本。人们不会期望修改该副本来修改原始文件。

其次,您应该通过调用-beginEditing-endEditing来包含文本存储的所有修改。实际上,你真的应该在文本视图中调用-shouldChangeTextInRange:replacementString:-didChangeText来改变。

最后,不需要枚举属性字符串,只从其存在的范围中删除属性。只需删除整个选择范围的属性即可。

所以:

- (void)emphasizeText {
    NSColor *c = [colorWell.color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
    NSRange selection = textView1.selectedRange;
    if ([textView1 shouldChangeTextInRange:selection replacementString:nil])
    {
        NSTextStorage* storage = textView1.textStorage;
        [storage beginEditing];
        [storage addAttributes:@{NSBackgroundColorAttributeName:c} range:selection];
        [storage endEditing];
        [textView1 didChangeText];
    }
}

- (void)deemphasizeText {
    NSRange selection = textView1.selectedRange;
    if ([textView1 shouldChangeTextInRange:selection replacementString:nil])
    {
        NSTextStorage* storage = textView1.textStorage;
        [storage beginEditing];
        [storage removeAttribute:NSBackgroundColorAttributeName range:selection];
        [storage endEditing];
        [textView1 didChangeText];
    }
}

需要考虑的其他事项:

  • 调整选择范围以适合您正在进行的修改。致电-rangeForUserCharacterAttributeChange;检查其位置是否为NSNotFound,如果是,则中止;检查它是否与当前selectedRange不同,如果是,请将selectedRange设置为匹配;然后在该范围内操作。
  • 使用-rangesForUserCharacterAttributeChange-shouldChangeTextInRanges:replacementStrings:支持多个选择范围。