在NSTableView中不调用textShouldEndEditing

时间:2012-04-03 08:15:05

标签: xcode nstableview objective-c-2.0 nstableviewcell

当用户添加新的托管对象时,它会显示在一个表格中,该表格向下滚动到新条目,新对象的名称(默认值)将进入编辑模式。

我需要检查数据存储区中新对象的名称是否唯一,因此我不能使用格式化程序。我认为,只要用户尝试使用textShouldEndEditing:提交条目的名称值,我应该验证这一点的完美时刻。

我将NSTableView子类化并覆盖以下方法,只是为了能够在日志中检查它们是否被调用。

- (BOOL)textShouldEndEditing:(NSText *)textObject {
    NSLog(@"textSHOULDendEditing fired in MyTableView");
    return [super textShouldEndEditing:textObject];
}
- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor {
    NSLog(@"control:textShouldEndEditing fired in MyTableView");
    return YES;
}
- (void)textDidEndEditing:(NSNotification *)aNotification {
    NSLog(@"textDIDEndEditing fired in MyTableView");
}

textDidEndEditing:被称为罚款,但textShouldEndEditing:没有。

NSTableView Class Reference中,在文本委派方法下,列出了textShouldEndEditing:textDidEndEditing:两种方法。有人请解释为什么一个人被召唤而另一个没有。


我认为NSTableView充当NSTextField的委托,该NSTextFieldCell被实例化为NSTextField黑匣子委托。因此NSTableView Class Reference中所谓的委托方法实际上实现了NSTextFieldCell对象的文本操作方法。

我尝试将NSTableView声明为NSTableView中的插座。我还试图在#import <AppKit/AppKit.h> #import <Cocoa/Cocoa.h> @interface MyTableView : NSTableView <NSTextDelegate, NSTextFieldDelegate, NSControlTextEditingDelegate, NSTableViewDelegate, NSTableViewDataSource> { } @end

中声明几个协议
{{1}}

不要笑,我甚至试图将我的表视图声明为自己的委托:P

3 个答案:

答案 0 :(得分:6)

在没有在Apple文档中找到任何确凿答案的情况下,在这个问题上敲了一整天之后,我决定分享我找到的解决方案,以防其他人在遇到同样的问题。

根据文档,正如原始海报所提到的,control:textShouldBeginEditing的{​​{1}}和control:textShouldEndEditing方法应该在代理上直接

  

此消息由控件直接发送到其委托对象。

此外,技术问答由Apple发布,标题为Detecting the start and end edit sessions of a cell in NSTableView,其中明确说明如下:

  

答:如何在NSTableView中检测单元格的开始和结束编辑会话?

     

为了检测用户何时开始和结束NSControlTextEditingDelegate中单元格的编辑会话,您需要设置为该表的委托并实现以下NSTableView委托方法:

     

NSControl

     

- (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor;

     

该表使用- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor;方法将从文本视图获取的委托消息转发到您的委托对象。这样,您的代理可以被告知文本视图字段编辑器代表它执行哪个控件。

我在Apple的文档中发现没有表明任何不同的内容,如果有人这样做,那么文档指针真的很受欢迎。

实际上,如果正在使用基于单元格的control:textShouldEndEditing:,这似乎是 true 。但是,只要将表更改为基于视图的表,委托方法就会在表委托对象上不再被调用

解决方案

但是,我执行的一些启发式测试表明,如果(并且据我所知:并且仅在以下情况下),在基于视图的表委托上调用这些委托方法:

  • 已设置表委托。
  • 设置了可编辑控件的代理。

如果删除任一委托,则不会调用NSTableView协议的方法。

根据the (only) documentation的意外情况是设置可编辑控件的委托。另一方面,将委托对象设置为接收委托通知听起来相当直观给我,这就是我首先尝试的原因。但有一个问题!然而,奇怪的是,就足够了。如果删除了表委托,即使设置了可编辑控件的委托,也不会调用NSControlTextEditingDelegate方法(对我来说这是最奇怪的事情)。

希望这有助于其他人不要在这个问题上浪费时间。

答案 1 :(得分:1)

在您的问题中,您提到插入“托管对象”,这就是问题所在。您似乎正在使用基于视图的表,但仅为基于单元格的表调用textShouldEndEditing:方法。

答案 2 :(得分:0)

我在(子类)托管对象中覆盖-(void)awakeFromInsert;,为name-property构造一个唯一的默认值。

另外,我最终没有覆盖表视图中的-(BOOL)textShouldEndEditing:方法。相反,我检查(子类)托管对象的-(BOOL)validate<Key>:error:中新输入的名称属性是否唯一。

总之,上述两种策略会在所有托管对象中产生唯一的名称属性。

也许我可以迫使NSTextFieldCell进入编辑模式,每次都会调用-(BOOL)textShouldEndEditing:


但有些评论:

-(BOOL)textShouldEndEditing:返回NO时,似乎-(BOOL)validate<Key>:error:返回NO。

仅当用户实际对属性进行更改时,-(BOOL)textShouldEndEditing:-(BOOL)validate<Key>:error:方法才会被称为