简体   繁体   English

如何制作包含属性文本但仅复制纯文本的 NSTextField

[英]How can I make an NSTextField containing attributed text but only copy plain text

I have an NSTextField subclass which uses a NSTextFieldCell subclass which contains an attributed string.我有一个NSTextField子类,它使用一个包含属性字符串的NSTextFieldCell子类。 I would like it if when the user copies text that it be copied to the pasteboard without the attributes.如果用户复制文本时将其复制到没有属性的粘贴板,我会喜欢它。

I have tried subclassing NSTextView , overriding copy: and setting isFieldEditor to YES and returning this new editor from the cells fieldEditorForView method.我已经尝试子类化NSTextView ,覆盖copy:并将isFieldEditor设置为YES并从单元格fieldEditorForView方法返回这个新编辑器。 While this copies only the plain text whenever it is used I have text drawn on text drawn on text (and so on ...) and if the underlying attributed string is changed by another control the field editor remains unmodified.虽然这只会在使用时复制纯文本,但我在文本上绘制的文本上绘制了文本(等等......),如果底层属性字符串被另一个控件更改,则字段编辑器保持不变。 When I do not use MyFieldEditor and let the NSTextFieldCell subclass use the default implementation this issue does not occur.当我不使用MyFieldEditor并让NSTextFieldCell子类使用默认实现时,不会发生此问题。

Is there a simpler solution to this problem?这个问题有更简单的解决方案吗?

Is there something additional that I need to override or receive delegate messages for?我需要覆盖或接收委托消息的其他内容吗?

MyFieldCell.m

- (NSTextView *)fieldEditorForView:(NSView *)controlView
{
    MyFieldEditor *editor = [[MyFieldEditor alloc] init];
    [super setUpFieldEditorAttributes:editor];

    return editor;
}

MyFieldEditor.m

@implementation MyFieldEditor

- (instancetype)init
{
    if ( (self = [super init]) )
    {
        [self setFieldEditor:YES];
    }

    return self;
}

- (NSString *)selectedString
{
    return [[self string] substringWithRange:[self selectedRange]];
}

- (void)copy:(id)sender
{
    [[NSPasteboard generalPasteboard] setString:[self selectedString] forType:NSPasteboardTypeString];
}

@end

Note: I am using ARC.注意:我正在使用 ARC。

Display Issue Image显示问题图像

绘图问题

Please find below what should be changed.请在下面找到应该更改的内容。 Tested & works with Xcode 11.2.1 / macOS 10.15.2 with no display issues.已测试并与 Xcode 11.2.1 / macOS 10.15.2 配合使用,没有显示问题。

a) No custom NSTextFieldCell and NSTextField are needed, so used just default a) 不需要自定义NSTextFieldCellNSTextField ,所以默认使用

b) Change to following in MyFieldEditor.m b) 在MyFieldEditor.m更改为以下MyFieldEditor.m

- (void)copy:(id)sender
{
    [NSPasteboard.generalPasteboard declareTypes:@[NSPasteboardTypeString] owner:self];
    [NSPasteboard.generalPasteboard setString:[self selectedString] forType:NSPasteboardTypeString];
}

c) Add window delegate method substituting field editor for targeted textfield (this is the valid documented way to provide custom field editors) c) 添加窗口委托方法,用字段编辑器替换目标文本字段(这是提供自定义字段编辑器的有效记录方式)

- (nullable id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(nullable id)client {
    if (client == self.textField) { // << in this case it is outlet
        return MyFieldEditor.new;
    }
    return nil;
}

Update:更新:

Overriding NSTextFieldCell as below and assigning it in XIB for targeted NSTextField instead of above NSWindow delegate method gives the same valid behaviour.如下覆盖 NSTextFieldCell 并在 XIB 中将其分配给目标 NSTextField 而不是上面的 NSWindow 委托方法给出了相同的有效行为。

@interface MyTextCell: NSTextFieldCell
@end

@implementation MyTextCell
- (nullable NSTextView *)fieldEditorForView:(NSView *)controlView {
    id editor = MyFieldEditor.new;
    [super setUpFieldEditorAttributes:editor];
    return editor;
}
@end

The issue is fieldEditorForView: is called repeatedly.问题是fieldEditorForView:被重复调用。 Every time it's called it creates a new MyFieldEditor and doesn't get rid of the old field editor.每次调用它都会创建一个新的MyFieldEditor并且不会摆脱旧的字段编辑器。

An NSWindow has only one field editor which it reuses. NSWindow只有一个可以重用的字段编辑器。 I guess the assumption is that any field editor of a given type should only ever be created once and should be reused.我想假设是给定类型的任何字段编辑器都应该只创建一次并且应该被重用。 As such a static variable referencing the editor and a nil check to create provides a lazy reusable editor.因此,引用编辑器的静态变量和创建的nil检查提供了一个懒惰的可重用编辑器。

@interface MyFieldCell: NSTextFieldCell
@end

@implementation MyFieldCell
- (nullable NSTextView *)fieldEditorForView:(NSView *)controlView
{
    static MyFieldEditor *kEditor;

    if ( kEditor ) { return kEditor; }
    kEditor = [[MyFieldEditor alloc] init];

    return kEditor;
}
@end

It would be nice if the editor could be made weak though.不过,如果编辑器可以变弱就好了。 Unfortunately NSTextView and its subclasses are incompatible with weak references.不幸的是NSTextView及其子类与弱引用不兼容。 If anyone has a cleaver idea around this I am all ears.如果有人对此有一个切肉刀的想法,我会全神贯注。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM