根据Apple's documentation on [NSTableViewDelegate tableView:shouldEditTableColumn:row:]
,“此方法仅对基于NSCell的表视图有效”。与基于视图的表视图相同的是什么?我想用自定义编辑体验替换默认的内联编辑。
答案 0 :(得分:2)
这个委托方法实际上不需要基于视图的表视图。
在这种情况下,您需要创建一些NSView子类。也可能有nib文件。
让我们说,你有一个名为CustomCellView的类有一些插座。 CustomCellView.h
档案
#define kCustomCellViewReusableIdentifier @"kCustomCellViewReusableIdentifier" // NSTableView reuses cell views
@interface CustomCellView : NSView
@property (weak) IBOutlet NSImageView *imageView;
@property (weak) IBOutlet NSTextField *textField;
- (void)setCellEditable:(BOOL)editable;
@end
这是您的CustomCellView.m
文件
@implementation CustomCellView
- (void)awakeFromNib
{
// paste your ui initializing code here
}
- (void)prepareForReuse
{
// this method will call each time cell reuses
}
- (void)setCellEditable:(BOOL)editable
{
[self.textField setEditable:editable];
// some other code
}
@end
不要忘记创建nib文件并连接你的网点。您的NSTableView所有者类必须具有一些用于重用的初始化代码。 MyTableViewController.m
- (void)initUI
{
NSString *nibName = NSStringFromClass([CustomCellView class]);
[self.tableView registerNib:[[NSNib alloc] initWithNibNamed:nibName bundle:nil]
forIdentifier:kCustomCellViewReusableIdentifier];
}
#pragma mark - table view data source methods
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
CustomCellView *view=[tableView makeViewWithIdentifier:kCustomCellViewReusableIdentifier owner:nil];
[view setCellEditable:someCondition]; //
return view;
}
#pragma mark - operations
- (void)setViewAtColumn:(NSTableColumn *)tableColumn row:(NSInteger)row editable:(BOOL)editable
{
CustomCellView *view=[self.tableView viewAtColumn:tableColumn row:row makeIfNecessary:NO]; //no need to create it if it's not exists - we'll set the data in NSTableViewDataSource method
if (view) // if it's exists
[view setCellEditable:editable];
}
答案 1 :(得分:1)
评论Astoria的方法:
每当模型的可编辑性发生变化时,必须更改文本字段的可编辑性的“不足”问题是,您必须“主动”跟踪模型的可编辑性并更新文本字段的可编辑性。
相比之下,基于单元格的表格视图的委托方法延迟了对可编辑性的关注,直到用户尝试进行编辑的时刻为止,此时委托只返回是否可以编辑模型。设置更少,错误的可能性更小。 (例如,根据您在模型中监视/响应可编辑性的方式,您可能会错过更改,现在用户可能会错误地编辑或不编辑该字段。)
因此,另一种方法是在用户尝试编辑时重新创建确定可编辑性的委派。要做到这一点,你要继承NSTextField
,覆盖“正确的位置”,询问代表,允许或禁止可编辑性。
“正确的位置”似乎会覆盖acceptsFirstResponder
,并返回NO。
- (BOOL)acceptsFirstResponder
{
BOOL accepts = [super acceptsFirstResponder];
if (accepts) {
if ([self.delegate respondsToSelector:@selector(textFieldShouldBecomeEditable:)]) {
accepts = [self.delegate textFieldShouldBecomeEditable:self];
}
}
return accepts;
}
使用上述内容,只要字段的editable
为YES,就会调用委托进行最终确定。
根据您的应用程序,这可能是一种更理想的方法,因为监控模型可编辑性的变化并不是直截了当的。但是,通常,简单设置字段editable
属性的标准方法是最佳的。
答案 2 :(得分:0)
根据seth的回答,我想到了这一点;需要对象(项目)上下文以及column和tableView信息。 HTH
// We cannot alter a playitem once plays is non-zero; set to zero to alter
@objc func textFieldShouldBecomeEditable(_ textField: PlayTableTextField) -> Bool {
let tableView = textField.superview?.superview?.superview as! PlayTableView
let item = (textField.superview as! PlayTableCellView).objectValue
let tableColumn = textField.tableColumn!
if tableView == playlistTableView, let playlist : PlayList = item as? PlayList {
guard playlist.name != UserSettings.HistoryName.value else { return false }
return tableColumn.identifier == .name
}
else
if tableView == playitemTableView, let playitem : PlayItem = item as? PlayItem {
let virgin = playitem.plays == 0
guard playitem.name != UserSettings.HistoryName.value else { return false }
switch tableColumn.identifier {
case .link:
return !virgin && !appDelegate.isSandboxed
case .plays:
return true
default:
return virgin || ![.link,.plays].contains(tableColumn.identifier)
}
}
else
{
return false
}
}