首页 » iOS编程基础:Swift、Xcode和Cocoa入门指南 » iOS编程基础:Swift、Xcode和Cocoa入门指南全文在线阅读

《iOS编程基础:Swift、Xcode和Cocoa入门指南》11.2 子类化

关灯直达底部

内建的Cocoa类所定义的方法可能会被Cocoa本身所调用,也可能需要在子类中重写,这样在调用方法时才会执行自定义行为而不仅仅是默认行为。

第10章曾介绍过的一个示例是UIView的drawRect:,它就是我所说的功能性事件。通过在UIView子类中重写drawRect:,你可以描绘出视图绘制自身的完整过程。你并不知道该方法何时会被调用,你也不在意这个;确定的是在绘制时,它能够确保视图总是按照你所期望的样子呈现出来(你永远不会自己调用drawRect:;如果底层情况发生了变化,你希望视图重绘,那么就需要调用setNeedsDisplay并让Cocoa调用drawRect:进行响应)。

内建的UIView子类还有其他一些功能性事件方法需要你通过子类化进行定制。一般来说,定制的目的在于改变视图的绘制方式,但又不需要自己控制完整的绘制过程。第10章提及的一个示例涉及了UILabel及其drawTextInRect:。另一个类似的示例是UISlider,你可以通过重写thumbRectForBounds:trackRect:value:来自定义滚动条“拇指”的位置与尺寸。

UIViewController这个类的设计目的就是让你子类化。在UIViewController类文档所列出的方法中,几乎全部方法都有重写的必要。如果在Xcode中创建了一个UIViewController子类,那么你会看到模板中已经包含了一些重写的方法供你起步。比如,viewDidLoad会被调用以便让你知晓视图控制器已经获得了其主视图(即它的视图),这样就可以进行初始化了;显然,这是个生命周期事件。UIViewController还有其他很多生命周期事件,你可以重写它们对发生的事情进行控制。比如,viewWillAppear:表示视图控制器的视图将会被放置到界面上;viewDidAppear:表示视图控制器的视图已经被放置到了界面上;viewDidLayoutSubviews表示视图已经在其父视图中定位了,诸如此类。

我称supportedInterfaceOrientations之类的UIViewController方法为查询事件。你的任务就是返回一个位掩码来告诉Cocoa,视图在某个时刻可以处于哪个方向。你相信Cocoa会在恰当的时刻调用这个方法,这样如果用户旋转了设备,应用的界面就会根据返回值决定旋转还是不旋转。

在寻找通过子类化可以接收到的事件时,请记得沿着继承体系向上查找。比如,如果想知道在将自定义UILabel子类嵌入另一个视图时如何收到通知,你不应该在UILabel类文档中寻求答案;UILabel是个UIView,因此它会接收到恰当的事件。在UIView类文档中,你会发现可以通过重写didMoveToSuperview以便在这种情况下接收到通知。同样,还要记得沿着所使用的协议向上查找。如果想知道当视图控制器的视图将要旋转时该如何收到通知,你不应该在UIViewController类文档中寻求答案;UIViewController使用了UIContentContainer协议,因此它会接收到恰当的事件。在UIContentContainer协议文档中,你会发现可以通过重写viewWillTransitionToSize:withTransitionCoordinator:来做到这一点。

不过,正如第10章所述,子类化与重写并非接收事件最重要与最常见的方式。除了UIViewController,我们很少会为了这个目的而子类化其他内建的Cocoa类。那么,你的代码还可以通过哪些方式接收事件呢?这正是本章所要介绍的主题。