【发布时间】:2022-03-10 05:29:50
【问题描述】:
我正在尝试将一些非常旧的、以前功能强大的 MacOS 代码(Objective C,pre-10.7)更新到现代 MacOS 和 XCode 13。我有一个基于 NSCell 的 NSTableView,它具有自定义行高,在编译 pre-10.7 时可以正常工作,而且还有更多最近已经停止工作。回想一下 10.7 是引入自动布局和修改 NSTableView 以适应基于 NSView 的单元格的时代,因此在这个以前的功能代码中的一些问题在那个时候被刷新是有道理的。
“停止工作”的症状是我的自定义 NSCell 的绘图方法 (drawWithFrame:inView) 从未被调用,并且 NSTableView 将每一行呈现为两个像素高的不透明矩形。 8年前有人举报a similar symptom in similar global circumstances,但这个问题一直没有解决,他们不再活跃。
在 Interface Builder 中,我设置了“行大小样式:自定义”和“内容模式:基于单元格”。我相信自动布局是不相关的,因为 NSCells 没有约束。
现在是奇怪的部分。如果我删除我的 NSTableViewDelegate 的 heightOfRow 方法,表格渲染效果很好,并且自定义行渲染虽然都在一个恒定的高度。
但是,如果我重新添加一个简单的实现:
- (float)tableView:(NSTableView *)tableView heightOfRow:(int)row
{
return 30.0;
}
然后我可以看到这个方法被调用,每行一次,以累积它们的大小,但之后 NSCell 的 draw 方法永远不会被调用。
万一我完全误解了 heightOfRow 的文档,我也尝试返回比 30.0 大得多和小得多的数字。没运气。表格在未实现的 heightOfRow 下完美呈现的事实让我相信我的 dataSource 架构甚至我的自定义 NSCell 架构都可以正常工作,并且这个问题在某种程度上与 NSTableView 如何解释我的表格行有关。
和这里的面板(一个模态对话框)的(玩弄的)ViewController的源代码,它既包含tableView又充当它的代表:
/* A customCell, installed in our nib, allows us to do our custom rendering */
@interface CustomCell : NSCell
{
}
@end
@implementation CustomCell
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
CGContextRef quartz = [NSGraphicsContext currentContext].CGContext;
CGContextSaveGState(quartz);
CGContextSetRGBFillColor(quartz, 1.0, 0.0, 0.0, 1.0);
CGContextFillEllipseInRect(quartz, cellFrame);
CGContextRestoreGState(quartz);
}
@end
@implementation GSPRDBBrowseDialogController
#undef SHOW_THE_BUG
#ifdef SHOW_THE_BUG
/*
SHOW THE BUG: Explicitly including any definition of the
following delegate method, even one that returns a constant row
height of 30, causes our [cell drawWithFrame] method to never be called,
and all table rows appear as black rectangles 2 pixels high.
*/
- (float)tableView:(NSTableView *)tableView heightOfRow:(int)row
{
return 30;
}
#else
/* with no implementation of heightOfRow, Cocoa calls our renderer using
some the constant row height value (24 pixels) specified in the nib.
*/
#endif
- (IBAction) openButtonPressed: (id) sender
{
[NSApp stopModal];
}
- (id) initWithContext: (const RDB_Context*) iContext
helpContext: (int) iHelpContext
{
rdbContext = *iContext;
return( self = [super initWithNibNamed: @\"rdbbrowse_dlg\"
dialogData: NULL
changeProc: NULL
backTrack: false
helpContext: iHelpContext]);
}
- (int) numberOfRowsInTableView: (NSTableView*) iTableView
{
return 20;
}
- (id) tableView: (NSTableView*) iTableView
objectValueForTableColumn: (NSTableColumn*) iColumn
row: (int) iRow
{
return nil; // doesn\'t matter. real code returns more here.
}
@end
使用 SHOW_THE_BUG #UNDEFined 运行此代码会产生以下正确(但不希望出现的)结果:20 行红色圆圈,每行 24 像素高:
但是更改为#DEFINE SHOW_THE_BUG,从而包括一个玩具实现的heightOfRow,它应该将所有行设置为30像素高,相反我们得到这个......细长的矩形(仔细查看表格的顶部)和实际的单元格渲染器(drawWithFrame)是从来没有打电话:
关于我的代码可能会出现什么疯狂扭曲的任何想法,定义一个有效恒定的自定义行高会完全中断渲染但未定义行高会产生近乎完美的结果?
谢谢, 缺口
-
没有看到它,我们无法判断您的代码有什么问题。基于单元的
NSTableView已被弃用并且越来越多。转换为基于视图的NSTableView是一种选择吗? -
谢谢@Willeke。我想尝试基于视图的表格是我的终极选择;我没有意识到 NSCells 已被正式弃用。当这么多 NSTableView 配置在 Interface Builder 中时,尝试显示代码非常令人沮丧!将尝试使用程序分配进行复制,然后发布。
-
@Willeke 我添加了源代码(IB 部分的屏幕截图)。有吸烟枪吗?
-
我尝试了您的代码(在 macOS 10.15 上),但没有发现任何问题。我无法将控件大小设置为大。
tableView.usesAutomaticRowHeights的值是多少?
标签: macos cocoa nstableview