在 NSTokenField 中混合标记和字符串
Mixing tokens and strings in NSTokenField
我想要一个包含纯文本和标记的 NSTokenField
。这与 this question 中的问题相同,但那里的答案并没有为我解决。也许我遗漏了什么,或者苹果在发布这些答案后的 5 年里改变了一些东西。
具体来说,假设我想输入 "hello%tok%" 并将其变成这样:
为了尝试消除混淆的可能性,我总是使用以下 类 之一的自定义表示对象,而不是纯字符串...
@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" 时,委托方法的 none 被调用,这似乎是合理的。当我键入第一个“%”时,有 3 个委托调用:
tokenField:representedObjectForEditingString:
获取字符串 "hello" 并将其转换为 WrappedString
表示形式。
tokenField:styleForRepresentedObject:
得到 WrappedString
和 returns NSPlainTextTokenStyle
.
tokenField:editingStringForRepresentedObject:
得到 WrappedString
和 returns "hello".
前两个调用似乎是合理的。我不确定第 3 个,因为令牌应该是可编辑的,但它还没有被编辑。我原以为 tokenField:displayStringForRepresentedObject:
会被调用,但它没有。
当我键入 "tok" 时,没有调用委托方法。当我键入第二个“%”时,tokenField:representedObjectForEditingString:
收到字符串 "hellotok",而我本以为只会看到 "tok"。所以我从来没有机会创建圆形令牌。
如果我以其他顺序键入文本,“%tok%hello”,那么我会得到预期的结果,一个圆形标记后跟纯文本 "hello"。
顺便说一句,Token Field Programming Guide 说
Note that there can be only one token per token field that is configured for the plain-text token style.
这似乎暗示不可能自由混合纯文本和标记。
我问自己是否在标准应用程序中的任何地方看到过混合文本和标记,我确实看到过。在系统偏好设置的语言和文本面板中,在格式选项卡下,单击"Customize..." 按钮会弹出一个包含标记字段的对话框。这是其中的一部分。
在这里,您不是通过键入标记化字符来创建标记,而是拖放原型标记。
要制作其中一个原型令牌,请制作另一个 NSTokenField
并将其设置为没有背景或边框并且可选择但不可编辑。当您的 window 加载后,您可以使用 objectValue
属性 初始化原型字段,例如
self.protoToken.objectValue = @[[[[Token alloc] init] autorelease]];
您需要为每个原型令牌字段以及您的可编辑令牌字段设置一个委托。为了能够拖放标记,您的代表必须实现 tokenField:writeRepresentedObjects:toPasteboard:
和 tokenField:readFromPasteboard:
.
我想要一个包含纯文本和标记的 NSTokenField
。这与 this question 中的问题相同,但那里的答案并没有为我解决。也许我遗漏了什么,或者苹果在发布这些答案后的 5 年里改变了一些东西。
具体来说,假设我想输入 "hello%tok%" 并将其变成这样:
为了尝试消除混淆的可能性,我总是使用以下 类 之一的自定义表示对象,而不是纯字符串...
@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" 时,委托方法的 none 被调用,这似乎是合理的。当我键入第一个“%”时,有 3 个委托调用:
tokenField:representedObjectForEditingString:
获取字符串 "hello" 并将其转换为WrappedString
表示形式。tokenField:styleForRepresentedObject:
得到WrappedString
和 returnsNSPlainTextTokenStyle
.tokenField:editingStringForRepresentedObject:
得到WrappedString
和 returns "hello".
前两个调用似乎是合理的。我不确定第 3 个,因为令牌应该是可编辑的,但它还没有被编辑。我原以为 tokenField:displayStringForRepresentedObject:
会被调用,但它没有。
当我键入 "tok" 时,没有调用委托方法。当我键入第二个“%”时,tokenField:representedObjectForEditingString:
收到字符串 "hellotok",而我本以为只会看到 "tok"。所以我从来没有机会创建圆形令牌。
如果我以其他顺序键入文本,“%tok%hello”,那么我会得到预期的结果,一个圆形标记后跟纯文本 "hello"。
顺便说一句,Token Field Programming Guide 说
Note that there can be only one token per token field that is configured for the plain-text token style.
这似乎暗示不可能自由混合纯文本和标记。
我问自己是否在标准应用程序中的任何地方看到过混合文本和标记,我确实看到过。在系统偏好设置的语言和文本面板中,在格式选项卡下,单击"Customize..." 按钮会弹出一个包含标记字段的对话框。这是其中的一部分。
在这里,您不是通过键入标记化字符来创建标记,而是拖放原型标记。
要制作其中一个原型令牌,请制作另一个 NSTokenField
并将其设置为没有背景或边框并且可选择但不可编辑。当您的 window 加载后,您可以使用 objectValue
属性 初始化原型字段,例如
self.protoToken.objectValue = @[[[[Token alloc] init] autorelease]];
您需要为每个原型令牌字段以及您的可编辑令牌字段设置一个委托。为了能够拖放标记,您的代表必须实现 tokenField:writeRepresentedObjects:toPasteboard:
和 tokenField:readFromPasteboard:
.