我正在构建一个NSTableView
来显示一组文件路径(directoriesArray
)。我在main.storyboard上构建了NSTableView,我使用了这段代码:
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return _directoriesArray.count;
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
return [_directoriesArray objectAtIndex:row];
}
- (void)tableViewSelectionDidChange:(NSNotification *)notification {
NSTableView *tableView = notification.object;
NSLog(@"User has selected row %ld", (long)tableView.selectedRow);
NSLog(@"%@",[_directoriesArray objectAtIndex:tableView.selectedRow]);
}
//changes font of everything
- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSTextFieldCell *cell = [tableColumn dataCell];
[cell setFont:[self quicksand:15.0f]];
return cell;
}
这很有效。
我现在想要遍历NSTableView
上的每个单元格并使用if语句编辑它们。
我尝试过更换
- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
阻止,用:
-(NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{
NSTableCellView *view = [tableView makeViewWithIdentifier:[tableColumn identifier] owner:self];
if(view == nil){
NSTableCellView *view = [[NSTableCellView alloc]initWithFrame:[tableView frame]];
view.identifier = [tableColumn identifier];
}
NSTextField *textfield = [[NSTextField alloc]initWithFrame:NSMakeRect(0, 0, 100, 30)];
[textfield setStringValue:[_directoriesArray objectAtIndex:tableView.selectedRow]];
[textfield setBackgroundColor:[NSColor redColor]];
[view addSubview:textfield];
[view setNeedsDisplay:YES];
return view;
}
但这显示空行!我做错了什么?!
奇怪的是 - 当我修改代码运行时点击一个单元格tableViewSelectionDidChange
被调用,我仍然可以完美地获取日志....?!
我已经更新了代码(尽我所能 - 这很糟糕):
-(NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{
NSTableCellView *view = [tableView makeViewWithIdentifier:[tableColumn identifier] owner:self];
if(view == nil){
NSTableCellView *view = [[NSTableCellView alloc]initWithFrame:[tableView frame]];
view.identifier = [tableColumn identifier];
view.translatesAutoresizingMaskIntoConstraints = false; //turned this off
NSTextField *textfield;
textfield.autoresizingMask = NSViewMaxXMargin | NSViewMinYMargin; //changed to autoresizing
[textfield setStringValue:[_directoriesArray objectAtIndex:row]]; //changed to row
[textfield setBackgroundColor:[NSColor redColor]];
[view addSubview:textfield];
[view setNeedsDisplay:YES];
}
return view;
}
答案 0 :(得分:3)
这个问题似乎很困惑。主题说它是关于遍历表格视图的单元格,但其中似乎没有任何内容,因此。
您说您使用-tableView:dataCellForTableColumn:row:
方法替换了-tableView:viewForTableColumn:row:
方法。第一个适用于基于单元格的表格视图。第二个是基于视图的表视图。通过更改您的委托方法,您可以将表格从基于单元格更改为基于视图。
对于以编程方式创建的表视图,我认为委托方法是唯一决定它是基于单元格还是基于视图的方法。但是,对于在故事板中创建的表视图,也会在故事板中指定。两者不匹配肯定会造成麻烦。
因此,如果您想从基于单元格切换到基于视图,请确保在故事板中更改它。在这种情况下,您也可以在故事板中设置原型单元格视图。
您可以在代码中创建单元格视图。由于您没有关闭translatesAutoresizingMaskIntoConstraints
(默认情况下已启用),因此您的单元格视图及其文本字段实际上是使用spring-and-struts模型进行布局。表视图将设置单元视图的框架。但是,您最初将其设置为巨大 - 与整个表视图一样大。此外,文本字段最初位于(0,0,100,30)。您需要设置其autoresizingMask
以确定在单元格视图的大小更改时其大小应如何更改。并且,如果将其设置为在其superview调整大小时调整大小,那么您希望superview具有更合理的大小(或者文本字段几乎不合理)。
您要避免的场景是单元格视图开始很大,文本字段相对较小,文本字段配置为大致与单元格视图的大小成比例,因此当表格视图将单元格视图的大小调整为单元格的大小,将文本字段缩小到极小的大小。
在创建单元视图之前,请求表视图从其重用队列中获取一个。这很好。但是,如果它从其重用队列中获取一个,那么那个已经有一个文本字段。您不应每次都创建和添加新的文本字段。文本字段的创建应该在if(view == nil)
语句中。
当您设置文本字段stringValue
时,您正使用_directoriesArray
为tableView.selectedRow
编入索引。这是错的。首先,表格视图可能没有selectedRow
。事实上,它不可能在它首次建立时。我很惊讶你因为使用错误的索引(-1)索引到数组而没有得到异常。其次,为所有不同的行调用您正在实现的方法。你不想给他们所有相同的价值。该方法传递一个row
参数,该参数指示视图已被请求的行。
为了更好地衡量,我会将单元格视图的textField
插座连接到您创建的文本字段。 NSTableCellView
有时根据其textField
出口连接做特殊事情。 (例如,它使用文本字段的内容作为单元格的辅助功能文本。)
在您编辑的新代码中,存在新问题。
您正在关闭translatesAutoresizingMaskIntoConstraints
以查看单元格视图。我并不是说你把它关掉了。我只是在解释它的存在以及它的后果是什么。对于单元格视图,您应该将其保持打开状态,并让表视图决定是否要将其关闭。通常,将视图插入视图层次结构的控制器代码决定是否关闭该视图。但是,还有那些仍然没有意识到自动布局或属性的控制器代码,因此默认情况下它应保持打开状态。这样,自动布局感知控制器代码可以根据需要设置它,而自动布局 - 初始控制器代码获取它所依赖的旧行为。 (从技术上讲,我们不能假设NSTableView
的内部是否在这个意义上是自动布局感知的。)
您根本不再创建文本字段。您声明了变量,但是您没有创建实例。该变量只保留nil
(假设您正在使用ARC)。您仍应分配并初始化文本字段。但是,您应该使用框架矩形作为单元格视图和文本字段,它们具有您希望它们具有的空间关系。弹簧和支柱只保持关系。所以,你需要从一个合理的关系开始,然后使用autoresizingMask
来维护它。
如果您决定使用自动布局将文本字段与其超级视图(单元格视图)相关联,则可以在文本字段上关闭关闭。但是,您需要建立约束以将文本字段与单元格视图相关联。在这种情况下,单元格视图和文本字段的初始帧无关紧要。
在新代码中,您只需在创建文本字段时设置translatesAutoresizingMaskIntoConstraints
。但是,如果从重用队列中获取它,则需要设置它。如果在创建两者时设置单元格视图的stringValue
属性,则执行此操作会更容易。
以下是您的代码的修订版本:
textField