是否可以在 Interface Builder 中设计 NSCell 子类?
我正在尝试将 NSCell 子类化以在 NSTableView 中使用。 我想要创建的单元相当复杂,因此如果我可以在 Interface Builder 中设计它,然后从笔尖加载 NSCell,那将非常有用。
这可能吗? 我该怎么做?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
问题是关于 NSCell 的子类; 其他答案似乎在做其他事情,可能利用 UITableViewCell 作为视图。
NSCell 不是一个视图。 虽然在 IB 中放置自定义单元将是一件有用的事情,但我认为答案基本上是“不,这是不可能的”。 当你继承 NSCell 时,你几乎只是在做你自己的绘图。 不支持子单元格或参数化自动布局(ala NSView 的弹簧和支柱),我怀疑您正在寻找什么。
唯一需要注意的是,您可以设计一个 NSCell 子类,它会进行子元素的布局,并提供用于设置这些子元素和所有可调整参数的参数。 然后,您需要编写一个 IB 插件,以使该单元和随附的检查器在 IB 中的设计时可用。
然而,这可能比编写一个执行或多或少相同功能的小型自定义应用程序更困难。 将 NSCell 放在窗口中间的控件中,并为自己制作 UI 来调整您感兴趣的参数。绑定可以使定位内容变得非常简单(即将 x 值绑定到滑块),尽管您会当然不能直接操纵元素。 完成后,您可以存档单元格并在运行时在实际应用程序中加载存档,或者您可以仅注销属性并在应用程序中的代码中设置它们。
The question was about a subclass of NSCell; the other answers seem to be doing something else, likely taking advantage of UITableViewCell being a view.
NSCell is not a view. While laying a custom cell out in IB would be a useful thing to be able to do, I think the answer is basically "no, this is not possible". When you subclass NSCell, you're pretty much just doing your own drawing. There isn't support subcells, or parameterized auto layout (ala NSView's springs and struts), which is I suspect what you're looking for.
The only caveat is that you could design an NSCell subclass that did do layout of sub-elements and provided parameters for setting those subelements and all tweakable parameters. Then, you would need to write an IB plugin to make that cell and accompanying inspector available at design time in IB.
This, however, is probably harder than writing a little custom app that does more or less the same thing. Put an NSCell in a control in the middle of a window, and make yourself UI for tweaking the parameters you're interested in. Bindings can make this pretty straightforward for positioning stuff (i.e. bind an x value to a slider), though you will not get direct manipulation of the elements of course. When you're done, you could archive your cell and load the archive at runtime in your real app, or you could just log out the properties and set them in code in your app.
这个线程中的一些答案已经偏离主题,因为他们谈论的是 Cocoa Touch,而最初的问题是关于 Cocoa 的 - 2 个 API 在这方面有很大不同,Cocoa Touch 使这变得很容易,因为 UITableViewCell 是一个视图子类。 NSCell 不是,这就是问题
所在 作为信息,我最近不得不在 NSOutlineView 中做一些非常类似的事情 - 基本上是相同的,但如果有的话有点难,因为你必须处理级别的披露/崩溃。 如果您对代码感兴趣,我在这里发布了它: http://www.stevestreeting.com/2010/08/08/cocoa-tip-using-custom-table-outline-cells-Design-in-ib/< /a>
HTH
Some answers in this thread have gone off topic because they're talking about Cocoa Touch, when the original question was about Cocoa - the 2 APIs are quite different in this regard and Cocoa Touch makes it easy because UITableViewCell is a view subclass. NSCell isn't, and that's the problem
For information, I had to do something very similar in NSOutlineView recently - which is basically the same, but a little harder if anything because you have to deal with disclosure / collapse of levels. If you're interested in the code, I posted about it here: http://www.stevestreeting.com/2010/08/08/cocoa-tip-using-custom-table-outline-cells-designed-in-ib/
HTH
正如 Ken 所说,
NSCells
和NSViews
是不同的,你只能在 NIB 中布局NSView
层次结构,而不是NSCells
> (没有任何明确的层次结构)。另一方面,没有什么可以阻止您拥有
NSViews
层次结构并使用它来绘制NSCell
——您可以将它们添加为单元格父视图的子视图,告诉它们展示,然后将它们从窗口移走,没有人会更明智。在这种情况下,使用 NIB 就可以了,尽管看起来很麻烦。 通常,我只是将采用
NSCells
的对象替换为采用我的NSViews
的自定义对象,但这意味着编写您自己的鼠标处理代码,这非常敏感。另一方面,我的方法允许您在 NIB 中绑定视图的值,因此您不必做任何额外的工作,这很酷。
As Ken says,
NSCells
andNSViews
are different, and you can only lay outNSView
hierarchies in NIB, notNSCells
(which don't have any explicit hierarchy).On the other hand, there's nothing preventing you from having a hierarchy of
NSViews
and using that to draw yourNSCell
-- you could add them as a subview of your cell's parent view, tell them to display, and remove them from the window and nobody would be the wiser.In this case, using a NIB would work, although it seems like a ton of hassle. Typically I've just replaced the object that takes
NSCells
with a custom one that takes myNSViews
, but that means writing your own mouse-handling code, which is very touchy.On the other hand, my approach lets you bind the views' values in NIB, so you don't have to do any extra work, which is cool.
在 IB 中,启动一个空的 XIB。 现在转到调色板并拖入 UITableViewCell,双击以调出并编辑。
仅包含自定义 UITableViewCell(没有其他 UIView 或其他顶级控件) - 确保它是 IB 中真正的 UITableViewCell,否则您无法设置重用标识符(与将 IB 中的 UIView 强制转换为自定义 UITableViewCell 类相反)。
然后,您可以在单元格中添加标签或任何您喜欢的内容,以及设置重用标识符或设置您可能喜欢的任何公开指示符。
要使用,您可以在 tableView:cellForRow:atIndexPath: 方法中提供如下代码:
如果您想要在代码中引用任何标签或其他控件,请在 IB 中将它们连接到您的自定义单元格类 - 而不是文件的所有者,该类您不需要使用上面的代码进行设置(您可以将其保留为 NSObject)。
编辑:我注意到您确实在寻找 NSCell 答案,但是在 Cocoa 中使用 IB 的代码方法应该与我上面使用的 Cocoa Touch 代码相同,因为 loadNibNamed 是标准的 Cocoa 调用。
In IB, start an empty XIB. Now go to the pallete and drag in a UITableViewCell, double click to bring up and edit.
include only the custom UITableViewCell (no other UIViews or other top level controls) - make sure it's a real UITableViewCell in IB, or you cannot set a reuse identifier (as opposed to casting a UIView in IB as your custom UITableViewCell class).
Then you can add lables or whatever you like within the cell, as well as setting the reuse identifier or set whatever disclosure indicator you might like.
To use, you provide code like this in the tableView:cellForRow:atIndexPath: method:
If you have any labels or other controls you want to reference in your code, wire them in IB to your custom cell class - NOT the file's owner, which you do not ever need to set using the above code (you can leave it as NSObject).
Edit: I note you are really looking for an NSCell answer, but the code approach to using IB should be identical in Cocoa with the Cocoa Touch code I used above as loadNibNamed is a standard Cocoa call.
Joar Wingfors 几年前为 Stepwise 撰写了一篇关于相关主题的文章,TableView 行中的子视图 。
主要技术是创建一个可以托管 NSView 的 NSCell。 如果您要这样做,您可以在 Interface Builder 中设计一个 NSView 子类,您可以将其嵌入到需要该特定单元格的任何位置。
另一种可能性,如果你可以针对 Leopard,看看你是否需要使用 NSTableView 或者是否可以使用 NSCollectionView。 集合视图直接处理“项目视图”而不是单元格,因此它们在 Interface Builder 中设计起来更加简单。
Joar Wingfors wrote an article for Stepwise a few years back on a related topic, Subviews in TableView Rows.
The principal technique is to create an NSCell that can host an NSView. If you were to do this, you could then design an NSView subclass in Interface Builder that you could embed anywhere you need that specific cell.
Another possibility, if you can target Leopard, is to see whether you need to use an NSTableView or whether you can use an NSCollectionView. Collection views deal directly in terms of "item views" rather than in cells, so they're much more straightforward to design in Interface Builder.
我发现了一些有趣的例子,但我并不完全理解。
最后 2 个示例使用
NSTableViewDataSource
和NSTableViewDelegate
。 我想在InterfaceBuilder
中使用Bindings
和ArrayController
来连接其他 UI 元素(例如文本字段)。我偶然发现了另一个讨论,其中< a href="https://stackoverflow.com/users/41116/abizern">Abizern 指出 Alex Rozanski 的 PXListView 看起来非常有前途!
我正在尝试自己解决该问题。 请在 github 上找到我的项目和最新的此处出现渲染问题。
I found some interesting examples which I do not totally understand, though.
NSTextFieldCell
in their PBIconAndTextCell, referencing this post.The last 2 examples work with
NSTableViewDataSource
andNSTableViewDelegate
. I would like to useBindings
anArrayController
in theInterfaceBuilder
to connect other UI elements like text fields.I stumbled into another discussion where Abizern points out PXListView by Alex Rozanski which looks very promising!
I am trying to implement a solution for the problem myself. Please find my project on github and the latest rendering problems over here.
我这样做是这样的:
但是它不是很有效,如果您加载大量数据,它可能会伤害您。 当然,您应该使用reuseIdentifier,它应该强制此代码在每个表中仅运行几次。
I do it like this:
However it isn't very efficient and if you're loading lot of data it might hurt you. Of course you should be using a reuseIdentifier which should force this code to only run a handful of times per table.
1) 创建
NSViewController
TableViewCell.h
2) 在
TableViewCell.h
中创建一些过程,如3) 在主类中
#import "TableViewCell .h"
4) 在
-(NSView *)tableView:viewForTableColumn:row: write: 中的主类中
希望这会有所帮助 =)
1) Create
NSViewController
TableViewCell.h
2) Create in
TableViewCell.h
some procedures like3) In Main class
#import "TableViewCell.h"
4) In Main class in
-(NSView *)tableView:viewForTableColumn:row: write:
Hope this will help =)
我想在这里提供一种更现代的方法。
从 iOS 5 开始,UITableView 有一个方法
(void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
一旦您注册了包含单元格的 NIB,只需使用
- (id )dequeueReusableCellWithIdentifier:(NSString *)identifier
获取新单元格。 如果一个单元格可供重用,它将被返回,否则会自动创建一个新单元格,在这种情况下,这意味着从 NIB 文件加载。
I want to provide a more modern approach here.
Starting with iOS 5, UITableView has a method
(void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
Once you registered your NIB containing your cell, just use
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
to get a new cell. If a cell is available for reuse, it will be returned, otherwise a new cell is automatically created, and in that case this means loaded from the NIB file.
将您的
UITableViewCell
添加到您的tableviewcontroller
并声明一个IBOutlet
属性:...然后在
cellForRowAtIndexPath
中您可以使用您的单元格并将其设置为重复使用:Add your
UITableViewCell
to yourtableviewcontroller
and declare anIBOutlet
property:... then in
cellForRowAtIndexPath
you can just use your cell and set it to be reused: