作为一个初学者,我一直很弄不明白NSCell
的子类,比如,NSButtonCell
,NSImageCell
及其对应的控件之间的关系。今天,在做一个TableView实现的时候,我终于开始有点悟了——好吧,你大可以鄙视我,我的脑袋是不灵光。尽管这是一个简单的问题,但是我还是简单的记录一下我的理解。
问题的起源是“Cocoa Programming For Mac OS X”上一段关于NSCell
的叙述:
NSControl inherits from NSView. With its graphics context, NSView is a relatively large and expensive object to create. When the NSButton class was created, the first thing someone did was to create a calculator with 10 rows and 10 columns of buttons. The performance was less than it could have been because of the 100 tiny views. Later, someone had the clever idea of moving the brains of the button into another object (not a view) and creating one big view (called an NSMatrix) that would act as the view for all 100 button brains. The class for the button brains was called NSButtonCell.
— Chapter 17. Custom Views, “For the More Curious: Cells”
现在在此阅读这句话,我似乎已经能够基本理解,不过当时那叫一个困惑啊。为什么用Cell就比Button性能高呢?为什么Cell可以替代Button呢?
我的理解如下(可能并不是很精确):
NSButton
的继承关系是:NSButton
–>NSControl
–>NSView
–>NSResponder
–>NSObject
。应该说,是一个很长的继承链了。NSButtonCell
的继承关系是:NSButtonCell
–>NSCell
–>NSObject
。
比之NSButton
,少了两层继承关系。光凭这一点大致就能够解释为什么Cell的性能比Control高很多了。
但是既然Cell和Control都代表了“控件”,那么两者又是怎样的关系呢?
查阅了苹果的文档之后,就发现里面有这么一句话:“The NSButton class uses NSButtonCell to implement its user interface.”
这么一来,一切都清楚了,NSCell
是控件的UI显示部分。但是NSCell
不是NSView
的子类,它又怎么显示自己呢?在NSButton
的文档里,又有下面的一段话:
NSButton and NSMatrix both provide a control view, which is needed to display an NSButtonCell object. However, while NSMatrix requires you to access the NSButtonCell objects directly, most of the NSButton class’ methods are “covers” for identically declared methods in NSButtonCell. (In other words, the implementation of the NSButton method invokes the corresponding NSButtonCell method for you, allowing you to be unconcerned with the existence of the NSButtonCell.)
这段话的大意是:
NSButton
和NSMatrix
能够为NSButtonCell
提供一个控制视图,用来实现Cell的显示。不过NSMatrix
需要直接操作NSButtonCell
对象,而NSButton
则不需要。因为它已经“封装”了所有NSButtonCell
的同名方法。也就是说,对NSButton
调用方法(不是所有的方法),实际上是对NSButtonCell
调用方法,调用的时候,我们甚至可以无需知道NSButtonCell
的存在。
至此,问题解决。甚至,以前没有联系起来的一个问题也解决了:那就是,为什么在Interface Builder中,NSButton
总是和NSButtonCell
同时存在的——原因,当然也是上面的那段话啦~另外,在Interface Builder里,NSButton
和NSButtonCell
的Inspector里的属性也基本相同,也是因为上述原因。
一点题外话:
UIKit里没有NSCell
的对应类。原因并不是很清楚。不过UIKit里的类的继承结构也与AppKit有所不同。比如,NSTableView
的列:NSTableColumn
采用的是Cell的显示机制;而UITableView
则采用的是UITableViewCell
。前者继承自NSObject
,后者继承自UIView
。
关于这样的区别在性能上的差别,我不敢妄下结论,也没法随便比较——毕竟是两个不同平台。似乎在iOS平台上,UITableView
的Cell会在离开显示区域的时候被release
掉——这可能是为什么iOS平台没有采用UICell
(没有这个类的!!!)的原因之一。
不过,我感觉UITableView
比NSTableView
更加灵活,自定义也更加方便——因为每个UITableViewCell
可以很方便的用一个Custom View
来做界面;而NSTableColumn
则依赖于NSCell
,要自定义,需要用自定义NSCell
的子类,这样会复杂很多。
本文转载自 http://cocoa.venj.me/blog/about-nscell/