为什么NSWindow的contentView属性类型为id?

时间:2012-02-06 16:44:16

标签: objective-c cocoa nsview nswindow

为什么类型为contentView的{​​{1}}类的NSWindow属性而不是id

这对我来说没有意义,为什么contentView应该是NSView子类以外的任何东西。

所以在我的情况下,我必须像这样输入它才能访问它的框架:

NSView

而不是编译器不喜欢的那样:

NSView *contentView = self.window.contentView; // returns an `id`
CGRect frame = contentView.frame

3 个答案:

答案 0 :(得分:9)

这可能是历史性的。 Objective-C支持严格的输入,但它也支持“duck typing”,你不关心对象是什么 class ,你关心它响应的消息(也就是说,如果它看起来像一只鸭子,它像鸭子一样嘎嘎叫,它可能是一只鸭子)。您可以将每个对象指针键入id并发送任何消息。实际上,接收者无需为其收到的任何消息实现方法:它也可以将消息转发给另一个对象。

在Application Kit中 - OpenStep和Cocoa的前身GUI框架 - 几乎所有对象都是通过duck typing来使用的。这是应用程序工具包3.2版本中Window的(部分)接口。

@interface Window : Responder
{
  NXRect frame;
  id contentView;
  id delegate;
  id firstResponder;
  id lastLeftHit;
  id lastRightHit;
  id counterpart;
  id fieldEditor;
  int winEventMask;
  int windowNum;
  float backgroundGray;
  //some bit masks indicating whether the window is visible, is key etc.
}
-contentView;
-setContentView:aView;
//more methods
@end

请注意,contentView ivar被定义为id,并且访问者方法中的所有类型也被隐式定义为id(所以-setContentView:返回一个对象:可能是Window实例self)。这就是20世纪90年代早期大多数Objective-C代码看起来的样子:应用工具包可能是20世纪90年代早期的大多数Objective-C代码。

NSWindow是在AppKit的第一个版本中引入的 - 1994年成为Cocoa的GUI框架.AppKit通常使用比Application Kit更严格的类型声明,但并没有严格遵守。实际上甚至可能是AppKit的NSWindow包含来自Application Kit的Window的代码,并且此contentView ivar未在更改中更新。

事实上,Objective-C变量中对类型一致性的严格要求是相对较新的。大多数严格性是通过属性声明(除了C存在并且支持强制类型之外的强类型)或者通过更改允许可选方法的协议引入的,因此可以严格地键入委托对象。

答案 1 :(得分:2)

-[NSWindow contentView]具有id类型的事实可能是Cocoa和Objective-C早期的遗留。

无论如何:编译器警告是您用于发送消息的属性样式语法的结果。在Cocoa中(与Cocoa-Touch相对)windowcontentViewframe不是其类的属性。这意味着您应该使用正常的消息发送语法:

CGRect frame = [[[self window] contentView] frame];

这将在没有编译器警告的情况下工作。

答案 2 :(得分:-1)

用于动态输入。 NSWindow如果它contentView真的是NSView,如果它响应发送的选择器,则NSView并不在乎。所以,这样你理论上可以创建自己的类,它不会继承{{1}}来显示内容,编译器也不会窒息。