我正在尝试将 NSCell 子类化以在 NSTableView 中使用。我要创建的单元格相当复杂,所以如果我可以在 Interface Builder 中设计它然后从 nib 加载 NSCell 将会非常有用。
这可能吗?我该怎么做?
我正在尝试将 NSCell 子类化以在 NSTableView 中使用。我要创建的单元格相当复杂,所以如果我可以在 Interface Builder 中设计它然后从 nib 加载 NSCell 将会非常有用。
这可能吗?我该怎么做?
问题是关于 NSCell 的一个子类;其他答案似乎在做其他事情,可能利用 UITableViewCell 作为视图。
NSCell 不是视图。虽然在 IB 中放置自定义单元将是一件有用的事情,但我认为答案基本上是“不,这是不可能的”。当你继承 NSCell 时,你几乎只是在做你自己的绘图。没有支持子单元或参数化的自动布局(ala NSView 的弹簧和支柱),我怀疑你在寻找什么。
唯一需要注意的是,您可以设计一个 NSCell 子类来进行子元素的布局并提供用于设置这些子元素和所有可调整参数的参数。然后,您需要编写一个 IB 插件,以使该单元格和随附的检查器在 IB 中的设计时可用。
然而,这可能比编写一个或多或少做同样事情的小定制应用程序更难。将 NSCell 放在窗口中间的控件中,并为自己制作 UI 以调整您感兴趣的参数。绑定可以使定位内容变得非常简单(即将 x 值绑定到滑块),尽管您会当然不能直接操纵元素。完成后,您可以存档您的单元格并在运行时在您的真实应用程序中加载存档,或者您可以注销属性并在您的应用程序的代码中设置它们。
该线程中的一些答案已经偏离主题,因为他们正在谈论 Cocoa Touch,而最初的问题是关于 Cocoa - 这两个 API 在这方面有很大不同,而 Cocoa Touch 使它变得容易,因为 UITableViewCell 是一个视图子类。NSCell 不是,这就是问题所在
对于信息,我最近不得不在 NSOutlineView 中做一些非常相似的事情 - 这基本上是相同的,但如果有的话,会有点困难,因为你必须处理级别的披露/崩溃。如果您对代码感兴趣,我在这里发布:http: //www.stevestreeting.com/2010/08/08/cocoa-tip-using-custom-table-outline-cells-design-in-ib /
高温高压
正如 Ken 所说,NSCells
andNSViews
是不同的,您只能NSView
在 NIB 中布置层次结构,而不是NSCells
(没有任何明确的层次结构)。
另一方面,没有什么能阻止你拥有一个层次结构NSViews
并使用它来绘制你的NSCell
——你可以将它们添加为你的单元格父视图的子视图,告诉它们显示,然后从窗口中删除它们,没有人会更聪明。
在这种情况下,使用 NIB 是可行的,尽管它看起来很麻烦。通常情况下,我只是用NSCells
带有 my 的自定义对象替换了带有 my的对象NSViews
,但这意味着要编写自己的鼠标处理代码,这非常棘手。
另一方面,我的方法可以让您在 NIB 中绑定视图的值,因此您不必做任何额外的工作,这很酷。
在 IB 中,启动一个空的 XIB。现在转到调色板并拖入一个 UITableViewCell,双击调出并进行编辑。
仅包括自定义 UITableViewCell(没有其他 UIView 或其他顶级控件) - 确保它是 IB 中的真实 UITableViewCell,或者您不能设置重用标识符(而不是将 IB 中的 UIView 强制转换为自定义 UITableViewCell 类)。然后,您可以在单元格中添加标签或您喜欢的任何内容,以及设置重用标识符或设置您可能喜欢的任何披露指示符。
要使用,您在 tableView:cellForRow:atIndexPath: 方法中提供如下代码:
YourCustomCellClass *cell = (YourCustomCellClass *)[tableView dequeueReusableCellWithIdentifier:<IDYouSetInXIBFile>];
if ( cell == nil )
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:<YourXIBName> owner:self options:nil];
id firstObject = [topLevelObjects objectAtIndex:0];
if ( [ firstObject isKindOfClass:[UITableViewCell class]] )
cell = firstObject;
else cell = [topLevelObjects objectAtIndex:1];
}
如果您有任何要在代码中引用的标签或其他控件,请将它们在 IB 中连接到您的自定义单元格类 - 而不是文件的所有者,您不需要使用上述代码进行设置(您可以将其保留为 NSObject )。
编辑:我注意到您确实在寻找 NSCell 答案,但是在 Cocoa 中使用 IB 的代码方法应该与我上面使用的 Cocoa Touch 代码相同,因为 loadNibNamed 是标准的 Cocoa 调用。
几年前,Joar Wingfors 为Stepwise写了一篇关于相关主题的文章,即 TableView Rows 中的子视图。
主要技术是创建一个可以承载 NSView 的 NSCell。如果你要这样做,你可以在 Interface Builder 中设计一个 NSView 子类,你可以将它嵌入到任何你需要该特定单元格的地方。
如果您可以针对 Leopard,另一种可能性是查看您是否需要使用 NSTableView 或是否可以使用 NSCollectionView。集合视图直接根据“项目视图”而不是单元格进行处理,因此在 Interface Builder 中设计它们要简单得多。
不过,我发现了一些我不完全理解的有趣的例子。
NSTextFieldCell
他们的PBIconAndTextCell,引用了这篇文章。最后两个示例使用NSTableViewDataSource
and NSTableViewDelegate
。我想使用Bindings
inArrayController
来InterfaceBuilder
连接其他 UI 元素,如文本字段。
我偶然发现了另一个讨论,其中Abizern指出Alex Rozanski的 PXListView看起来很有希望!
我正在尝试自己实施该问题的解决方案。请在 github 上找到我的项目,并在此处找到最新的渲染问题。
我这样做:
/* example of a silly way to load a UITableViewCell from a standalone nib */
+ (CEntryTableViewCell *)cell
{
// TODO -- this is really silly.
NSArray *theObjects = [[NSBundle mainBundle] loadNibNamed:@"EntryTableViewCell" owner:self options:NULL];
for (id theObject in theObjects)
if ([theObject isKindOfClass:self])
return(theObject);
NSAssert(NO, @"Could not find object of class CEntryTableViewCell in nib");
return(NULL);
}
但是,它不是很有效,如果您要加载大量数据,它可能会伤害您。当然,您应该使用重用标识符,它应该强制此代码在每个表中只运行几次。
我想在这里提供一种更现代的方法。
从 iOS 5 开始,UITableView 有一个方法
(void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
注册包含您的单元格的 NIB 后,只需使用
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
得到一个新的细胞。如果一个单元格可供重用,它将被返回,否则会自动创建一个新单元格,在这种情况下,这意味着从 NIB 文件中加载。
1) 创建NSViewController
TableViewCell.h
2)在TableViewCell.h
一些程序中创建,如
-(void)setText:(NSString *)text image:(NSImage *)image
3)在主类#import "TableViewCell.h"
4)在主类中 -(NSView *)tableView:viewForTableColumn:row: write:
NSImage *img = //some image
TableViewCell *cell = [[TableViewCell alloc] initWithWindowNibName:@"TableViewCell"];
cell.view.init;
[cell setText:@"some text" image:img];
return cell;
希望这会有所帮助=)
将您的添加UITableViewCell
到您的tableviewcontroller
并声明一个IBOutlet
属性:
@interface KuguTableViewController : UITableViewController {
IBOutlet UITableViewCell *customTypeCell;
}
@property (readonly) UITableViewCell *customTypeCell;
...然后cellForRowAtIndexPath
您可以使用您的单元格并将其设置为重复使用:
static NSString *CellIdentifier = @"CustomCell"
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = customTypeCell;
cell.reuseIdentifier = CellIdentifier;