在 NSTextField 上实现委托方法

Implement Delegate Method on NSTextField

我正在尝试在 NSTextField 上实现委托方法,如 Apple this article 中所述。我的目标是 NSTextField 接受回车符 returns 和制表符。我在其他地方(包括链接的文章)读到 NSTextView 是更好的选择。但是,我在一个不支持 NSTextView 的多平台框架内工作,如果我能让它接受运输 returns.

NSTextField 将完成这项工作

根据文章,这是我的代码:

@interface MyTextFieldSubclass : NSTextField
{}
- (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector;
@end

@implementation MyTextFieldSubclass
- (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector
{
   BOOL result = NO;

   if (commandSelector == @selector(insertNewline:))
   {
      // new line action:
      // always insert a line-break character and don’t cause the receiver to end editing
      [textView insertNewlineIgnoringFieldEditor:self];
      result = YES;
   }
   else if (commandSelector == @selector(insertTab:))
   {
      // tab action:
      // always insert a tab character and don’t cause the receiver to end editing
      [textView insertTabIgnoringFieldEditor:self];
      result = YES;
   }

   return result;
}
@end

此外,在文本字段的身份检查器中,我已将 class 名称从默认的 NSTextField 更改为我的 class 名称。但是,当我 运行 我的程序时,永远不会调用委托方法。我还需要做些什么才能在 Interface Builder 中进行设置吗?

您链接的文档中有几个相关部分我认为可能被忽略了。

我复制了以下几行:

Should you decide to keep using NSTextField, allowing the tab key and/or allowing enter and return keys for line-breaks can be achieved by implementing the following delegate method:

  • (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector;

Note: When implementing this delegate method in your own object you should set your object up as the "delegate" for this NSTextField.

我将一些我认为可能被遗漏的标注加粗了。

此方法在 NSControl.h 中的 NSControlTextEditingDelegate 协议中。因此,它应该由实现 NSControlTextEditingDelegate(即 NSTextFieldDelegate

的 class 实现

这样做的一种常见方法是让 ViewController“持有”NSTextField 成为 NSTextFieldDelegate.

这是一个非常简单的示例,使用您链接的 Apple 示例代码:

ViewController.h

#import <Cocoa/Cocoa.h>

@interface ViewController : NSViewController <NSTextFieldDelegate>


@end

ViewController.m

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view.
}


- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];

    // Update the view, if already loaded.
}

- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector {
    BOOL result = NO;
     
        if (commandSelector == @selector(insertNewline:))
        {
            // new line action:
            // always insert a line-break character and don’t cause the receiver to end editing
            [textView insertNewlineIgnoringFieldEditor:self];
            result = YES;
        }
        else if (commandSelector == @selector(insertTab:))
        {
            // tab action:
            // always insert a tab character and don’t cause the receiver to end editing
            [textView insertTabIgnoringFieldEditor:self];
            result = YES;
        }
     
    return result;
}


@end

然后将 NSTextField 的委托设置为 ViewController

无需添加自定义子class。

或者,您可以将自定义文本字段设为子class 它自己的委托。沿着这些线的东西:

#import "MyTextFieldSubclass.h"

@interface MyTextFieldSubclass() <NSTextFieldDelegate>
@end

@implementation MyTextFieldSubclass

- (instancetype)init {
    self = [super init];
    if (self) {
        self.delegate = self;
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    if (self) {
        self.delegate = self;
    }
    return self;
}

- (instancetype)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    if (self) {
        self.delegate = self;
    }
    return self;
}

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    
    // Drawing code here.
}

- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector {
    BOOL result = NO;

       if (commandSelector == @selector(insertNewline:))
       {
          // new line action:
          // always insert a line-break character and don’t cause the receiver to end editing
          [textView insertNewlineIgnoringFieldEditor:self];
          result = YES;
       }
       else if (commandSelector == @selector(insertTab:))
       {
          // tab action:
          // always insert a tab character and don’t cause the receiver to end editing
          [textView insertTabIgnoringFieldEditor:self];
          result = YES;
       }

       return result;
}

@end