gpt4 book ai didi

cocoa - NSTokenField 的 tokenField :completionsForSubstring:indexOfToken:indexOfSelectedItem: indexOfToken always zero

转载 作者:行者123 更新时间:2023-12-03 16:37:55 32 4
gpt4 key购买 nike

我已经使用基于文档的 ARC 应用程序尝试了 NSTokenField 的第一个简单示例,使我的 Document 类成为 NSTokenFieldDelegate。它可以工作,但有一点是:委托(delegate)方法 tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem: 永远不会看到除了 0 以外的任何内容,即使我成功编辑了一个不是 token 字符串中第一个的 token 。我在 OS X 10.8.2 上使用 XCode 4.5 和 10.8 框架。

问题:为什么总是0?我希望它是用户正在编辑的字段中间接可见的标记 0 .. n - 1 数组中标记的索引。

要重现,请按照上面的方式启动一个项目并添加下面的文本,然后使用 XIB 编辑器并将 NSTokenField 拖到文档窗口中,将 token 字段设置为文档的 tokenField 并使文档实例成为 token 字段的委托(delegate).

文档.h:

#import <Cocoa/Cocoa.h>

@interface Document : NSDocument <NSTokenFieldDelegate>
{
IBOutlet NSTokenField *tokenField; // of (Token *).
NSMutableDictionary *tokens; // of (Token *).
}
@end

Token.h:

#import <Foundation/Foundation.h>

@interface Token : NSObject
@property (strong, nonatomic) NSString *spelling;
- (id)initWithSpelling:(NSString *)s;
@end

Token.m:

#import "Token.h"

@implementation Token
@synthesize spelling;

- (id)initWithSpelling:(NSString *)s
{
self = [super init];
if (self)
spelling = s;
return self;
}

@end

文档.m:

#import "Document.h"
#import "Token.h"

@implementation Document

- (id)init
{
self = [super init];
if (self) {
tokens = [NSMutableDictionary dictionary];
}
return self;
}

...

#pragma mark NSTokenFieldDelegate methods

- (NSArray *)tokenField:(NSTokenField *)tokenField
completionsForSubstring:(NSString *)substring
indexOfToken:(NSInteger)tokenIndex
indexOfSelectedItem:(NSInteger *)selectedIndex
{
NSLog(@"tokenField:completionsForSubstring:\"%@\" indexOfToken:%ld indexOfSelectedItem:",
substring, tokenIndex);
NSMutableArray *result = [NSMutableArray array];
for (NSString *key in tokens) {
//NSLog(@"match? \"%@\"", key);
if ([key hasPrefix:substring])
[result addObject:key];
}
return result;
}

- (id)tokenField:(NSTokenField *)tokenField representedObjectForEditingString:(NSString *)editingString
{
NSLog(@"tokenField:representedObjectForEditingString:\"%@\"", editingString);
Token *token;
if ((token = [tokens objectForKey:editingString]) == nil) {
token = [[Token alloc] initWithSpelling:editingString];
[tokens setObject:token forKey:editingString];
//NSLog(@"token %@", [token description]);
NSLog(@"tokens %@", [tokens description]);
}
return token;
}

- (NSString *)tokenField:(NSTokenField *)tokenField displayStringForRepresentedObject:(id)representedObject
{
NSString *spelling = [representedObject spelling];
NSLog(@"tokenField:displayStringForRepresentedObject: = \"%@\"", spelling);
return spelling;
}

@end

token 的输入以换行符或逗号字符终止。

最佳答案

这绝对是你应该向 Apple 报告的事情。

为了确定 NSTokenField 中已编辑标记的索引,我首先创建了 NSTextView 的子类,以便拥有一个自定义字段编辑器。 (如果您选择这条路线,请不要忘记将您的 NSTextView 实例设置为具有 -[NSTextView setFieldEditor:] 的字段编辑器。)然后,我对 NSTokenFieldCell 进行子类化,将 -[NSCell fieldEditorForView:] 覆盖为

  1. 创建我的 NSTextView 子类的实例,
  2. 将此 NSTextView 实例设置为 self 的委托(delegate),并且
  3. 返回此NSTextView实例。

在您的 NSTextView 子类中实现 tokenFieldCell:completionsForSubstring:indexOfToken:indexOfSelectedItem::

- (NSArray *)tokenFieldCell:(NSTokenFieldCell *)tokenFieldCell completionsForSubstring:(NSString *)substring indexOfToken:(NSInteger)tokenIndex indexOfSelectedItem:(NSInteger *)selectedIndex
{
// The tokenIndex passed to this function seems to be 0 in all cases, so we
// need to determine the tokenIndex ourselves. The range returned by
// NSText's selectedRange method treats non-plain-text tokens as if they
// have unit length. So, for each token, subtract from the range location
// either the token's length if it's a plain text token, or 1 if it's any
// other style of token. Each time we subtract from the range location,
// increment tokenIndex. When the range location becomes less than or equal
// to 0, tokenIndex will be the index of the edited token.
tokenIndex = 0;
NSInteger rangeLocation = self.selectedRange.location;
for (id token in tokenFieldCell.objectValue) {
if ([self tokenFieldCell:tokenFieldCell styleForRepresentedObject:token] == NSPlainTextTokenStyle) {
rangeLocation -= [self tokenFieldCell:tokenFieldCell displayStringForRepresentedObject:token].length;
} else {
rangeLocation--;
}
if (rangeLocation > 0) {
tokenIndex++;
} else {
break;
}
}
}

这里的想法是利用这样一个事实:假设非纯文本标记的长度为 1,则计算 NSTextViewselectedRange。通过减去长度从 selectedRange 位置到该位置为负数的 token 数,我们可以确定 token 索引。

请注意,您的 NSTextView 子类还必须实现 tokenFieldCell:displayStringForRepresentedObject:tokenFieldCell:styleForRepresentedObject: 才能正常工作。

关于cocoa - NSTokenField 的 tokenField :completionsForSubstring:indexOfToken:indexOfSelectedItem: indexOfToken always zero,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12711825/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com