首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSTokenField不开火

NSTokenField不开火
EN

Stack Overflow用户
提问于 2015-02-08 14:28:13
回答 2查看 919关注 0票数 3

我有一个NSTokenField来向对象(文档)添加标记。我希望在令牌字段中添加令牌时(当键入标记字符时)使用新标记更新对象。不幸的是,这似乎行不通。NSTokenField连接到我的控制器中的一个动作,但是这个动作方法从未被调用。

我还有一个NSTextField以同样的方式连接到控制器,它在控制器中的动作方法被调用。

我也尝试过这一点,并进行了关键值观察:

代码语言:javascript
复制
- (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中的令牌被更改时,如何通知我?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-02-11 00:45:38

创建新标记时,不调用NSTokenField操作选择器。根据您在Interface中所使用的设置,当您单击enter到end编辑(仅发送Enter Enter)时,或者当您以其他方式结束编辑时(发送到end编辑),都会调用它。为了得到精确的控制,你需要另一种方法。

将标记字符添加到令牌字段时出现的蓝色标记称为文本附件(NSTextAttachment实例)。从令牌字段添加/删除标记的一种方法是跟踪令牌字段的基础属性字符串中包含的这些对象的数量的更改。

要访问相关的属性化字符串,您需要获得字段编辑器的layoutManager --这个对象最终提供了出现在文本视图中的字符串。一旦得到它,每次收到controlTextDidChange:消息时,都要数出它的attributedStringstring表示中的文本附件的数量。如果这一次的数字大于上一次计数中记录的数字,则刚刚添加了一个标记。

代码语言:javascript
复制
#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
票数 8
EN

Stack Overflow用户

发布于 2017-05-29 06:50:05

@patterson的代码端口到Swift 3:

代码语言:javascript
复制
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中产生预期的结果:

代码语言:javascript
复制
layoutManager.attributedString().string
    .split(by: Character(UnicodeScalar(NSAttachmentCharacter)!)).count

相反,当用户不键入时返回0,在编辑令牌时返回1。

代码语言:javascript
复制
let isEditing = layoutManager.attributedString().string
    .split(by: Character(UnicodeScalar(NSAttachmentCharacter)!)).count == 1

通过这两种方法的结合,您可以使用状态机编写自定义的“确实添加/删除令牌”回调。(但我不认为这是实现这一目标的非常安全的方式。)

  • 使用countAttachments(attributedString:)跟踪令牌的计数。
  • 使用isEditing检查.
    1. 如果用户开始添加一个新注释(新计数>旧计数&& isEditing == true)
    2. 如果用户开始编辑现有注释(新计数、==、旧计数& isEditing == true)
    3. 如果用户完成了一个令牌(oldIsEditing == true && newIsEditing == false)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28395047

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档