我在NSTextField中实现自动完成时遇到问题。我希望在用户输入+或@时触发自动完成功能。 (我以todo.txt格式自动完成项目和上下文。)
我对其进行编码的方式,当用户键入+时,它的工作方式完全符合预期,但当用户键入@时,它的行为不正常。我现在对其进行编码的方式,我的- (NSArray *)textView:(NSTextView *)textView completions:(NSArray *)words forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(int *)index
方法不会返回任何自动完成建议,因为charRange
不仅包含@符号,还包含@符号前面的单词和空格。
如果我更改此方法的工作方式,并且不要尝试将charRange
与我的关键字匹配,那么当@触发自动完成时,@符号之前的单词和空格也会被替换,当我只是希望更换@符号。
我已经将NSTextField子类化,并实现了几种方法来自定义内置的自动完成功能。我正在返回自动填充建议的自定义列表。我的代码如下。我已经阅读了Apple文档和谷歌搜索了几天试图解决这个问题。我认为我的做法可能是错误的,而且我愿意把这个问题抛在脑后,从更好的方法开始。
如果我可以修复传递给构建自动完成列表的方法的部分单词范围,那么我的方法会起作用。我知道Text View对象中有一个rangeForUserCompletion
方法,但我不知道如何使其工作。请帮忙!
#import <Cocoa/Cocoa.h>
@interface TETextField : NSTextField
@end
#define COMPLETION_DELAY (0.25)
@implementation TETextField
NSTimer *_completionTimer;
- (BOOL)acceptsFirstResponder {
return YES;
}
- (NSArray *)textView:(NSTextView *)textView completions:(NSArray *)words forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(int *)index
// this will be defined elsewhere
NSArray *keywords = @[@"@home", @"@work", @"@phone", @"+Report", @"+Presentation"];
NSString *partialString = [[textView string] substringWithRange:charRange];
NSLog(@"partialString: %@", partialString);
NSMutableArray *matches = [[NSMutableArray alloc] init];
for (NSString *string in keywords) {
if ([string rangeOfString:partialString
options:NSAnchoredSearch | NSCaseInsensitiveSearch
range:NSMakeRange(0, [string length])].location != NSNotFound)
{
[matches addObject:string];
}
}
[matches sortUsingSelector:@selector(compare:)];
return matches;
}
-(void)keyUp:(NSEvent *)event {
if ([[event characters] isEqualToString:@"@"] || [[event characters] isEqualToString:@"+"]) {
[self startCompletionTimer];
} else {
[self stopCompletionTimer];
}
[super keyUp:event];
}
- (void)doCompletion:(NSTimer *)timer {
[self stopCompletionTimer];
[self.currentEditor complete:self];
}
- (void)startCompletionTimer {
[self stopCompletionTimer];
_completionTimer = [NSTimer
scheduledTimerWithTimeInterval:COMPLETION_DELAY target:self
selector:@selector(doCompletion:) userInfo:nil repeats:NO];
}
- (void)stopCompletionTimer {
[_completionTimer invalidate];
_completionTimer = nil;
}
@end