NSTableView 不保留 NSTableCellView

NSTableView Not Retaining NSTableCellView

这是一个非常简单的 NSTableView,有 1 列和行,由 NSTableCellViews 组成,显示一个简单的字符串,我正在以编程方式设置它(没有 nib/interface 生成器)。

我无法让 table 视图显示字符串并且无法弄清楚为什么?!当我在显示 table 后捕获行选择事件时,单元格对象为零?!

我一定是在做一些非常愚蠢的事情,但我看不到。有什么想法吗?

@implementation PreferencesSelectorPanel
-(id)initWithWidth:(CGFloat)width
{
    self = [super init];
    if(self) {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        self.autoresizesSubviews = YES;

        _preferenceTypes = @[@"Settings 1", @"Settings 2", @"Settings 3", @"Settings 4", @"Settings 5"];

        _tv = [NSTableView new];
        _tv.translatesAutoresizingMaskIntoConstraints = NO;
        _tv.autoresizesSubviews = YES;
        _tv.focusRingType = NSFocusRingTypeNone;
        _tv.delegate = self;
        _tv.dataSource = self;
        _tv.rowHeight = 40;
        _tv.headerView = nil;
        _tv.selectionHighlightStyle = NSTableViewSelectionHighlightStyleRegular;
        _tv.allowsColumnReordering = NO;
        _tv.allowsColumnResizing = NO;
        _tv.allowsEmptySelection = NO;
        _tv.allowsTypeSelect = NO;
        _tv.gridStyleMask = NSTableViewSolidHorizontalGridLineMask;//NSTableViewGridNone;

        NSTableColumn *col1 = [[NSTableColumn alloc] initWithIdentifier:@"c1"];
        col1.resizingMask = NSTableColumnAutoresizingMask;
        [_tv addTableColumn:col1];

        [self addSubview:_tv];

        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(10)-[_tv(200)]-(>=10)-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_tv)]];
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(10)-[_tv]-(10)-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_tv)]];
    }
    return self;
}

-(NSInteger)numberOfRowsInTableView:(NSTableView *)tv
{
    NSLog(@"numberOfRowsInTableView");
    return _preferenceTypes.count;
}

-(NSView *)tableView:(NSTableView *)tv viewForTableColumn:(NSTableColumn *)tc row:(NSInteger)row
{
    NSTextField *tf = [NSTextField 
    labelWithString:_preferenceTypes[row]];
    tf.textColor = [NSColor blackColor];

    NSTableCellView *cell = [NSTableCellView new];
    cell.textField = tf;

    NSLog(@"Row for row %d with label:%@",(int)row, cell.textField.stringValue);
    return cell;
}

-(void)tableViewSelectionDidChange:(NSNotification *)notification
{
    NSTableCellView *cell = _tv.selectedCell;
    NSLog(@"%@", cell.textField.stringValue);
}
@end

这是记录到控制台的内容。我已经为此徘徊了几个小时,却一无所获:

2018-05-11 numberOfRowsInTableView
2018-05-11 Row for row 0 with label:Settings 1
2018-05-11 Row for row 1 with label:Settings 2
2018-05-11 Row for row 2 with label:Settings 3
2018-05-11 Row for row 3 with label:Settings 4
2018-05-11 Row for row 4 with label:Settings 5
2018-05-11 (null)
2018-05-11 (null)
2018-05-11 (null)

这是我得到的:

我无法弄清楚到底是什么问题。我得出了几个替代解决方案:

  1. 可以从 tableView:viewForTableColumn:row:
  2. 简单地 return 一个 NSTextField
  3. 也可以将 NSTextField 作为子视图添加到 NSTableCellView,但这样做会减少对布局的控制。
  4. 可以创建任何基于 NSView 的自定义控件。

我选择了最后一个并创建了一个外观和行为完全符合我要求的自定义 NSView。这就是我所做的。

@interface PreferenceTableViewCell : NSView
@property (nonnull, strong, readonly) NSTextField *tf;
@end

@implementation PreferenceTableViewCell
-(id)init
{
    self = [super init];
    if(self) {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        self.autoresizesSubviews = YES;
        _tf = [NSTextField labelWithString:@""];
        _tf.translatesAutoresizingMaskIntoConstraints = NO;
        _tf.autoresizesSubviews = YES;
        [self addSubview:_tf];
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(10)-[_tf]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_tf)]];
        [self addConstraint:[NSLayoutConstraint constraintWithItem:_tf attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    }
    return self;
 }
 @end