强制NSTextField发送textDidEndEditing

时间:2014-04-07 18:54:24

标签: objective-c macos cocoa subclass nstextfield

我有一个NSTextField的子类,所以当用户完成编辑字段时,文本字段将失去焦点。我也设置了它,所以每当用户点击主视图时,这将失去对文本字段的关注。这一切都很棒。现在我想为子类添加一些额外的功能。

我希望每次用户点击框外的任何位置时,textfield都会发送textDidEndEditing。这包括用户单击另一个UI组件的时间。我现在看到的行为是,当用户点击另一个UI组件时(让他们说一个组合框),该操作不会触发。有没有办法强迫这个?除了手动添加它作为其他组件操作的一部分?

任何帮助将不胜感激!

这里是我的textDidEndEditing函数的代码

- (void)textDidEndEditing:(NSNotification *)notification
{
  NSString *file = nil;
  char c = ' ';
  int index = 0;

  [super textDidEndEditing:notification];

  if ([self isEditable])
  {
    // is there a valid string to display?
    file = [self stringValue];
    if ([file length] > 0)
    {
      c = [file characterAtIndex:([file length] - 1)];
      if (c == '\n') // check for white space at the end
      {
        // whitespace at the end... remove
        NSMutableString *newfile = [[NSMutableString alloc] init];
        c = [file characterAtIndex:index++];
        do
        {
          [newfile appendFormat:@"%c", c];
          c = [file characterAtIndex:index++];
        }
        while ((c != '\n') && (index < [file length]));

        [self setStringValue:newfile];
        file = newfile;
      }

      [[NSNotificationCenter defaultCenter]
       postNotificationName:@"inputFileEntered" object:self];
    }
  }

  // since we're leaving this box, show no text in this box as selected.
  // and deselect this box as the first responder
  [self setSelectedText:0];
  [[NSNotificationCenter defaultCenter]
   postNotificationName:@"setResponderToNil" object:self];
}

其中&#34; setSelectedText&#34;是文本字段子类中的公共函数:

- (void)setSelectedText:(int) length
{
  int start = 0;
  NSText *editor = [self.window fieldEditor:YES forObject:self];
  NSRange range = {start, length};
  [editor setSelectedRange:range];
}

&#34; setResponderToNil&#34;通知是我的NSView子类的一部分:

- (void)setResponderToNil
{
  AppDelegate *delegate = (AppDelegate *)[NSApp delegate];
  [delegate.window makeFirstResponder:nil];
}

1 个答案:

答案 0 :(得分:0)

我想我找到了一种方法来做到这一点。它可能不是最有说服力的,但它似乎适用于我想要的行为类型。

我在应用程序的主控制器中添加了一个鼠标事件监听器:

event_monitor_mousedown_ = [NSEvent addLocalMonitorForEventsMatchingMask:NSRightMouseDown
                                                               handler:^NSEvent *(NSEvent * event)
{
  NSResponder *resp = [[[NSApplication sharedApplication] keyWindow] firstResponder];

    if ([resp isKindOfClass:[NSTextView class]])
    {
      // set UI in proper state - remove focus from text field
      // even when touching a new window for the first time
      [[NSNotificationCenter defaultCenter]
       postNotificationName:@"setResponderToNil" object:self];
      [self setStopState];
    }

  return event;
}];

此事件在任何mouseDown操作上检查应用程序中的当前响应者。如果它是一个textView对象(它是编辑NSTextField时第一个响应者的对象类型),它将发送通知以将firstResponder设置为nil。这会强制textDidEndEditing通知。我想再玩一下,看看我是否得到了正确的预期行为。我希望这可以帮助那里的人!