单击后恢复 NSAttributedString 的视觉状态

Restore the visual state of an NSAttributedString after having clicked on it

我需要在点击 NSAttributedString 后恢复它的视觉状态。

我的 NSAttributedString 包含 links 归因于范围。

在这个例子中,文本“@user”有一个 link 到 "htpp://somesite.com/":

let text = "Hey @user!"

let attr = NSMutableAttributedString(string: text)
let range = NSRange(location: 4, length: 5)
attr.addAttribute(NSForegroundColorAttributeName, value: NSColor.orange, range: range)
attr.addAttribute(NSLinkAttributeName, value: "htpp://somesite.com/", range: range)

let tf = NSTextField(frame: NSRect(x: 0, y: 0, width: 200, height: 50))
tf.allowsEditingTextAttributes = true
tf.isSelectable = true
tf.stringValue = text
tf.attributedStringValue = attr

它运行良好:单击文本字段中的“@user”,它会启动 URL。

但是一旦点击,属性颜色就会消失,取而代之的是蓝色,并添加下划线:

我找不到在单击字符串后恢复原始颜色的解决方案(或者完全避免这种自动更改)。

我见过 this and this 但没有实际的解决方案,我无法将指向的库集成到我的项目中(实际上我真的很想不必导入任何库)。

请注意,我现有的代码在 Swift 中,但我可以使用 Objective-C 解决方案。

单击 link 时,字段编辑器会显示文本。字段编辑器中的默认 link 文本样式为蓝色和下划线。

解决方案 1:在 NSTextFieldCell.

的子类中的 setUpFieldEditorAttributes: 覆盖中更改 link 的文本样式
- (NSText *)setUpFieldEditorAttributes:(NSText *)textObj {
    NSText *fieldEditor = [super setUpFieldEditorAttributes:textObj];
    if ([fieldEditor isKindOfClass:[NSTextView class]]) {
        NSMutableDictionary *linkAttributes = [((NSTextView *)fieldEditor).linkTextAttributes mutableCopy];
        linkAttributes[NSForegroundColorAttributeName] = [NSColor orangeColor];
        [linkAttributes removeObjectForKey:NSUnderlineStyleAttributeName];
        ((NSTextView *)fieldEditor).linkTextAttributes = linkAttributes;
    }
    return fieldEditor;
}

副作用:字段编辑器由 window 中的所有控件共享,所有控件现在将显示橙色 links。

解决方案 2:使用 fieldEditor:forObject: 方法或 NSWindowwindowWillReturnFieldEditor:toObject: 委托方法替换您自己的字段编辑器。文本字段有自己的字段编辑器,其他控件不会有橙色 link。不需要 NSTextFieldNSTextFieldCell 的子类。

示例:(AppDelegate 是 window 的委托)

@interface AppDelegate ()

@property (weak) IBOutlet NSWindow *window;
@property (weak) IBOutlet NSTextField *textField;
@property (nonatomic, strong) NSTextView *linkFieldEditor;

@end

@implementation AppDelegate

- (NSTextView *)linkFieldEditor {
    if (!_linkFieldEditor) {
        _linkFieldEditor = [[NSTextView alloc] initWithFrame:NSZeroRect];
        _linkFieldEditor.fieldEditor = YES;
        NSMutableDictionary *linkAttributes = [_linkFieldEditor.linkTextAttributes mutableCopy];
        linkAttributes[NSForegroundColorAttributeName] = [NSColor orangeColor];
        [linkAttributes removeObjectForKey:NSUnderlineStyleAttributeName];
        _linkFieldEditor.linkTextAttributes = linkAttributes;
    }
    return _linkFieldEditor;
}

- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)client {
    if (client == self.textField)
        return self.linkFieldEditor;
    else
        return nil;
}

解决方案 3:创建 NSTextFieldCell 的子类,实现 fieldEditorForView: 和 return 您自己的字段编辑器。这类似于解决方案 2,但由单元而不是 window 委托实现。

关于字段编辑器的文档:Text Fields, Text Views, and the Field Editor and Using a Custom Field Editor