我有一个NSTokenField来向对象(文档)添加标记。我希望在令牌字段中添加令牌时(当键入标记字符时)使用新标记更新对象。不幸的是,这似乎行不通。NSTokenField连接到我的控制器中的一个动作,但是这个动作方法从未被调用。
我还有一个NSTextField以同样的方式连接到控制器,它在控制器中的动作方法被调用。
我也尝试过这一点,并进行了关键值观察:
- (void) awakeFromNib {
[tokenField addObserver:self forKeyPath:@"objectValue" options:NSKeyValueObservingOptionNew context:NULL];
}
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if([object isEqual:tokenField]){
NSLog(@"Tokens changed");
}
}但是,只有在我以编程方式更改令牌时才会调用此操作。
当tokenField中的令牌被更改时,如何通知我?
发布于 2015-02-11 00:45:38
创建新标记时,不调用NSTokenField操作选择器。根据您在Interface中所使用的设置,当您单击enter到end编辑(仅发送Enter Enter)时,或者当您以其他方式结束编辑时(发送到end编辑),都会调用它。为了得到精确的控制,你需要另一种方法。
将标记字符添加到令牌字段时出现的蓝色标记称为文本附件(NSTextAttachment实例)。从令牌字段添加/删除标记的一种方法是跟踪令牌字段的基础属性字符串中包含的这些对象的数量的更改。
要访问相关的属性化字符串,您需要获得字段编辑器的layoutManager --这个对象最终提供了出现在文本视图中的字符串。一旦得到它,每次收到controlTextDidChange:消息时,都要数出它的attributedString的string表示中的文本附件的数量。如果这一次的数字大于上一次计数中记录的数字,则刚刚添加了一个标记。
#import "AppDelegate.h"
@interface AppDelegate ()
@property (weak) IBOutlet NSWindow *window;
@property (weak) NSLayoutManager *lm;
@property (nonatomic) NSUInteger tokenCount;
@end
@implementation AppDelegate
// The text in the fieldEditor has changed. If the number of attachments in the
// layoutManager's attributedString has changed, either a new tag has been added,
// or an existing tag has been deleted.
-(void)controlTextDidChange:(NSNotification *)obj {
NSUInteger updatedCount = [self countAttachmentsInAttributedString:self.lm.attributedString];
if (updatedCount > self.tokenCount) {
NSLog(@"ADDED");
self.tokenCount = updatedCount;
} else if (updatedCount < self.tokenCount) {
NSLog(@"REMOVED");
self.tokenCount = updatedCount;
}
}
// About to start editing - get access to the fieldEditor's layoutManager
-(BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor {
self.lm = [(NSTextView *)fieldEditor layoutManager];
return YES;
}
// Iterate through the characters in an attributed string looking for occurrences of
// the NSAttachmentCharacter.
- (NSInteger)countAttachmentsInAttributedString:(NSAttributedString *)attributedString {
NSString *string = [attributedString string];
NSUInteger maxIndex = string.length - 1;
NSUInteger counter = 0;
for (int i = 0; i < maxIndex + 1; i++) {
if ([string characterAtIndex:i] == NSAttachmentCharacter) {
counter++;
}
}
return counter;
}
@end发布于 2017-05-29 06:50:05
@patterson的代码端口到Swift 3:
override func controlTextDidChange(_ obj: Notification) {
guard let fieldEditor = self.tokenField.currentEditor() as? NSTextView,
let layoutManager = fieldEditor.layoutManager
else { return }
func countAttachments(attributedString: NSAttributedString) -> Int {
let string = attributedString.string as NSString
let maxIndex = string.length - 1
var counter = 0
for i in 0..<maxIndex {
if string.character(at: i) == unichar(NSAttachmentCharacter) {
counter += 1
}
}
return counter
}
let currentCount = countAttachments(attributedString: layoutManager.attributedString())
// cache count or act on it directly
}奇怪的是,以下内容并没有在Swift中产生预期的结果:
layoutManager.attributedString().string
.split(by: Character(UnicodeScalar(NSAttachmentCharacter)!)).count相反,当用户不键入时返回0,在编辑令牌时返回1。
let isEditing = layoutManager.attributedString().string
.split(by: Character(UnicodeScalar(NSAttachmentCharacter)!)).count == 1通过这两种方法的结合,您可以使用状态机编写自定义的“确实添加/删除令牌”回调。(但我不认为这是实现这一目标的非常安全的方式。)
countAttachments(attributedString:)跟踪令牌的计数。isEditing检查.
https://stackoverflow.com/questions/28395047
复制相似问题