在NSTokenField中混合标记和字符串

问题描述:

我想要一个包含纯文本和标记的NSTokenField。这与this question中的问题是一样的,但那里的答案还没有为我解决。也许我错过了一些东西,或者苹果公司在发布这些答案后的5年中改变了一些东西。在NSTokenField中混合标记和字符串

具体来说,假设我要输入“你好%TOK%”,并把它变成这样:

image of text "hello" and token "TOKEN"

为了尝试删除混乱的机会,我总是使用代表自定义对象,下面的类,而不是一个普通字符串之一...

@interface Token : NSObject 
@end 

@implementation Token 
@end 


@interface WrappedString : NSObject 
@property (retain) NSString* text; 
@end 

@implementation WrappedString 
@end 

这里是我的委托方法:

- (NSString *)tokenField:(NSTokenField *)tokenField 
    displayStringForRepresentedObject:(id)representedObject 
{ 
    NSString * displayString = nil; 
    if ([representedObject isKindOfClass: [WrappedString class]]) 
    { 
     displayString = ((WrappedString*)representedObject).text; 
    } 
    else 
    { 
     displayString = @"TOKEN"; 
    } 
    return displayString; 
} 

- (NSTokenStyle)tokenField:(NSTokenField *)tokenField 
       styleForRepresentedObject:(id)representedObject 
{ 
    NSTokenStyle theStyle = NSPlainTextTokenStyle; 
    if ([representedObject isKindOfClass: [Token class]]) 
    { 
     theStyle = NSRoundedTokenStyle; 
    } 

    return theStyle; 
} 

- (NSString *)tokenField:(NSTokenField *)tokenField 
     editingStringForRepresentedObject:(id)representedObject 
{ 
    NSString * editingString = representedObject; 
    if ([representedObject isKindOfClass: [Token class]]) 
    { 
     editingString = nil; 
    } 
    else 
    { 
     editingString = ((WrappedString*)representedObject).text; 
    } 
    return editingString; 
} 

- (id)tokenField:(NSTokenField *)tokenField 
    representedObjectForEditingString:(NSString *)editingString 
{ 
    id repOb = nil; 
    if ([editingString isEqualToString:@"tok"]) 
    { 
     repOb = [[[Token alloc] init] autorelease]; 
    } 
    else 
    { 
     WrappedString* wrapped = [[[WrappedString alloc] 
      init] autorelease]; 
     wrapped.text = editingString; 
     repOb = wrapped; 
    } 
    return repOb; 
} 

当我输入“hello”时,没有一个委托方法被调用,这似乎是合理的。当我键入第一个“%”,有3个代表电话:

  1. tokenField:representedObjectForEditingString:得到字符串“hello”,并把它变成一个WrappedString表示。
  2. tokenField:styleForRepresentedObject:得到WrappedString并返回NSPlainTextTokenStyle
  3. tokenField:editingStringForRepresentedObject:获取WrappedString并返回“hello”。

前两个调用似乎是合理的。我不确定3号,因为令牌应该是可编辑的,但它尚未被编辑。我会认为tokenField:displayStringForRepresentedObject:会被调用,但它不会。

当我输入“tok”时,没有委托方法被调用。当我输入第二个“%”时,tokenField:representedObjectForEditingString:收到字符串“hellotok”,我希望看到的只是“tok”。所以我从来没有机会创建圆形标记。

如果我按照其他顺序“%tok%hello”键入文本,那么我会得到预期的结果,一个圆形标记,后面跟一个普通的“hello”。

顺便说一句,在Token Field Programming Guide

注意,可以有每个被配置为纯文本标记风格令牌场只有一个令牌。

这似乎暗示它不可能*混合纯文本和标记。

+0

我认为苹果改变了一些东西,NSPlainTextTokenStyle不再工作。我不知道它是一个错误还是一个功能。旧的(2015)示例代码使用NSPlainTextTokenStyle,但它具有相同的问题,我无法再下载该示例。 – Willeke

我问自己我是否曾在标准应用程序的任何地方见过混合的文本和标记,而且我曾经见过。在系统预置语言文字&面板,则格式选项卡下,点击“自定义...”按钮之一带来了包含代码字段的对话框。这是一个部分。

enter image description here

在这里,你不通过键入一个符号化人物创建令牌,你拖放原型令牌。

要制作其中一个原型令牌,请创建另一个NSTokenField并将其设置为没有背景或边框,并且可以选择但不可编辑。当你的窗口已经加载,可以使用objectValue属性,例如初始化原型场,

self.protoToken.objectValue = @[[[[Token alloc] init] autorelease]]; 

您需要设置为每个原型标记领域的代表,以及您可编辑标记字段。为了能够拖放令牌,您的代理必须实施tokenField:writeRepresentedObjects:toPasteboard:tokenField:readFromPasteboard: