讀古今文學網 > iOS編程基礎:Swift、Xcode和Cocoa入門指南 > 11.2 子類化 >

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類。那麼,你的代碼還可以通過哪些方式接收事件呢?這正是本章所要介紹的主題。