前言
概述
你可以繼承UIViewController來展示的你的App的內(nèi)容义郑。大部分自定義的ViewController都是內(nèi)容型的ViewController,也就是說,它包含了所有的視圖,并負(fù)責(zé)為這些視圖提供數(shù)據(jù)。相反,容器型ViewController不擁有所有的視圖,它的部分子視圖被其他ViewController管理著劣领。自定義容器型ViewController和內(nèi)容型ViewController的步驟基本一樣,接下來我們會(huì)一一講到铁材。
對(duì)于內(nèi)容型ViewController尖淘,常見的分類有:
- UITableViewController, 當(dāng)你的ViewController的主View是一個(gè)表格時(shí)使用UITableViewController。
- UICollectionViewController著觉,當(dāng)你的ViewController的主View是一個(gè)集合性的視圖村生。
- UIViewController,所有其他類型的視圖饼丘。
對(duì)于容器類型的ViewController趁桃,父類取決于你是否修改了已存在的容器類。對(duì)于已存在的容器性視圖控制器肄鸽,選擇一個(gè)你想要修改的卫病,對(duì)于新的容器型ViewController,你可以子類化UIViewController典徘。關(guān)于創(chuàng)建一個(gè)容器型ViewController蟀苛,請(qǐng)參考 Implementing a Container View Controller
實(shí)現(xiàn)UI
你可以使用storyboard來實(shí)現(xiàn)ViewController的UI效果。雖然你也可以代碼來實(shí)現(xiàn)UI布局逮诲,但是storyboard是將視圖控制器的內(nèi)容可視化并為不同的環(huán)境定制視圖層次的絕佳方式帜平。可視化的UI構(gòu)建可以快速看到構(gòu)建結(jié)果而不必編譯和運(yùn)行App梅鹦。
下圖展示了一個(gè)storyboad的例子裆甩,每個(gè)長方形區(qū)域表示一個(gè)ViewController和與之相關(guān)的視圖。兩個(gè)ViewController之間的箭頭表示它們之間的關(guān)系和segues. 關(guān)系將容器型ViewController與它的子ViewController連接在一起齐唆。Segues 表示兩個(gè)ViewController之間的轉(zhuǎn)換淑掌。
每個(gè)新建的工程都有一個(gè) main storyboard, 它通常已經(jīng)包含一個(gè)或者多個(gè)ViewController。你可以在storyboard上從控件庫中拖拽出一個(gè)新的ViewController添加到面板上蝶念。新建的ViewController初始狀態(tài)下沒有與之關(guān)聯(lián)的類抛腕,必須通過設(shè)置“Identity inspector”給它賦予一個(gè)類。
使用storyboard編輯器可以做以下的操作:
- 為一個(gè)ViewController新增媒殉、編排担敌、配置視圖。
- 連接outlet和action廷蓉,參考:Handling User Interactions全封。
- 創(chuàng)建ViewController之間的關(guān)系和segues。參考: Using Segues桃犬。
- 為不同的size classes 設(shè)置布局刹悴。
- 為手勢(shì)來響應(yīng)視圖的交互操作。
如果沒有使用過storyboard構(gòu)建UI攒暇,你可以參考Start Developing iOS Apps Today這個(gè)教程來一步一步的學(xué)習(xí)土匀。
處理用戶交互
應(yīng)用程序的響應(yīng)者事件處理傳入的事件并采取適當(dāng)?shù)牟僮鳌1M管ViewController是響應(yīng)者對(duì)象形用,但它機(jī)會(huì)不直接處理事件就轧,ViewController通常采用如下幾種方式響應(yīng)用戶事件:
- ViewController定義action方法處理高級(jí)事件。Action 方法表示:
- 特定的動(dòng)作田度《视控件和視圖調(diào)用指定action方法來響應(yīng)特定的用戶操作。
- 手勢(shì)镇饺。手勢(shì)識(shí)別器調(diào)用指定的方法來告知手勢(shì)的當(dāng)前狀態(tài)乎莉。使用你自己的ViewController來處理手勢(shì)狀態(tài)的改變或者對(duì)整個(gè)手勢(shì)做出響應(yīng)。
- ViewController監(jiān)聽由系統(tǒng)或者其他對(duì)象發(fā)出的通知奸笤。上報(bào)通知變化是一種更新ViewController狀態(tài)的一種方式惋啃。
- ViewController作為其他對(duì)象的數(shù)據(jù)源或者代理。ViewController經(jīng)常用來作為table和collection view的數(shù)據(jù)源揭保。你也可以用它作為一個(gè)對(duì)象的代理如“CLLocationManager”對(duì)象肥橙,它通過代理告知地理位置的變更。
響應(yīng)事件經(jīng)常涉及到更新視圖的內(nèi)容秸侣,這需要擁有要更新視圖的引用存筏。你可以在ViewController中定義要修改內(nèi)容的視圖的outlet。下面代碼味榛,自定義ViewController中包含兩個(gè)outlets和一個(gè)action方法椭坚。
@interface MyViewController: UIViewController
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@property (weak, nonatomic) IBOutlet UITextField *myTextField;
- (IBAction)myButtonAction:(id)sender;
@end
class MyViewController: UIViewController {
@IBOutlet weak var myButton : UIButton!
@IBOutlet weak var myTextField : UITextField!
@IBAction func myButtonAction(sender: id)
}
在你的storyboard中,記得將你的ViewController的outlets和action方法和相應(yīng)的是視圖相連接搏色。在你的storyboard連接的outlets和actions確保他們?cè)谝晥D在被加載之后配置好善茎。關(guān)于如何在Xib中創(chuàng)建outlet和action參考:Builder connections Help。 關(guān)于如何處理事件频轿,參考:Event Hanlding Guide for iOS垂涯。
在運(yùn)行時(shí)展示你的視圖
Storyboard使得加載和展示ViewController的視圖的流程非常簡單烁焙。UIKit在它需要的使用視圖的時(shí)候會(huì)自動(dòng)從Storyboard中加載。作為加載流程的一部分耕赘,UIKit執(zhí)行以下任務(wù):
使用Storyboard中的信息實(shí)例化View
連接所有的outlets和actions
將根視圖賦值給ViewController的view屬性
-
調(diào)用ViewController的awakeFromNib
當(dāng)這個(gè)方法被調(diào)用的時(shí)候骄蝇,ViewController的特征集合還是空,視圖可能不在他們最終的位置上操骡。
-
調(diào)用ViewController的viewDidLoad方法
使用此方法添加或者移除視圖九火,修改布局約束,加載視圖所需要使用的數(shù)據(jù)册招。
在將ViewController的視圖展示在屏幕之前岔激,UIKit提供了一些額外的機(jī)會(huì)可以在視圖展示到屏幕前后對(duì)視圖進(jìn)行更改。需要指出的是是掰,下面方法將會(huì)被調(diào)用虑鼎。
- 調(diào)用ViewController的viewWillApper:方法是你知道視圖即將展示在屏幕上。
- 更新視圖的layout冀惭。
- 將視圖展示在屏幕上震叙。
- 調(diào)用viewDidAppear方法當(dāng)視圖已經(jīng)展示在屏幕上。
當(dāng)你增加散休,移除或者修改視圖或者視圖的位置和大小媒楼,記得同時(shí)要修改相應(yīng)視圖上的約束。對(duì)視圖的層級(jí)結(jié)構(gòu)進(jìn)行布局相關(guān)的更改會(huì)使得UIKit將layout標(biāo)記為“dirty”戚丸。在下一次更新循環(huán)中划址,layout引擎會(huì)比較視圖的大小和位置,使用當(dāng)前的約束應(yīng)用于改變的視圖層級(jí)限府。
關(guān)于不適用Storyboard創(chuàng)建視圖的方法夺颤,參考:UIViewController Class Referencep。
管理視圖布局
當(dāng)視圖的尺寸和位置發(fā)生改變胁勺,UIKit會(huì)更新你視圖的布局信息世澜。UIKit使用自動(dòng)布局引擎根據(jù)當(dāng)前的約束更新視圖。UIKit也可以讓其他感興趣的對(duì)象知道視圖的變化署穗,比如當(dāng)前正在展示的對(duì)象寥裂。
在布局處理的過程中,UIKit通過幾中方式通知你案疲,你可以執(zhí)行額外的與布局相關(guān)的操作封恰。使用這些通知來更新你的布局約束或者在在布局約束應(yīng)用之后做最終的調(diào)整。在布局期間褐啡,UIKit執(zhí)行以下操作來影響ViewController:
在需要的時(shí)候更新ViewController和它的視圖的特征集合诺舔。
調(diào)用viewWillLayoutSubviews方法。
調(diào)用當(dāng)前UIPresentationController的containerViewWillLayoutSubviews方法。
-
調(diào)用ViewController的根視圖的layoutSubViews方法低飒。
該方法的默認(rèn)實(shí)現(xiàn)是使用可用的約束計(jì)算新的布局许昨。之后該方法調(diào)用所有子視圖的layoutSubviews方法。
將計(jì)算后的布局信息應(yīng)用到視圖上逸嘀。
調(diào)用ViewController的viewDidLayoutSubviews方法车要。
調(diào)用當(dāng)前UIPresentationController對(duì)的containerViewDidLayoutSubviews方法。
ViewController可以使用viewWillLayoutSubviews和viewDidLayoutSubViews方法執(zhí)行額外的更新操作來影響布局操作崭倘。在布局之前,你可以增加或者移除視圖类垫,改變視圖的大小或者位置司光,更新約束或者更新相關(guān)視圖的屬性。布局之后悉患,你可能會(huì)重新加載table的數(shù)據(jù)残家,更新視圖的內(nèi)容,或者對(duì)視圖的大小和位置做出最后的調(diào)整售躁。
這里有幾個(gè)有效管理視圖的提示:
- 使用Auto Layout坞淮。使用autolayout創(chuàng)建的約束可以方便的將內(nèi)容在不同尺寸的屏幕上展示。
- 利用底部可底部的布局指南陪捷。使用這些布局指南可以確保內(nèi)容始終可見回窘。頂部布局指南影響著狀態(tài)欄和導(dǎo)航欄的高度。同樣的市袖,底部的布局指南影響著tabbar和toolbar的高度啡直。
- 記得在移除和添加視圖時(shí)更新約束。如果你動(dòng)態(tài)的增加和移除視圖苍碟,記得更新響應(yīng)的約束酒觅。
- ViewController的視圖執(zhí)行動(dòng)畫操作的時(shí)候暫時(shí)移除視圖。當(dāng)視圖使用UIKit的CoreAnimation執(zhí)行動(dòng)畫時(shí)微峰,在動(dòng)畫執(zhí)行期間移除約束舷丹,動(dòng)畫執(zhí)行完成之后再將約束添加回來。還有如果在視圖執(zhí)行動(dòng)畫期間蜓肆,如果改變了視圖的位置和大小要更新約束颜凯。
有關(guān)展示控制器以及它在ViewController的結(jié)構(gòu)中所扮演的角色,參考:The Presentation and Transition Process
高效管理內(nèi)存
盡管內(nèi)存分配的工作是由你來決定的症杏,下表中列出了UIViewController關(guān)于內(nèi)存創(chuàng)建和銷毀的常用方法装获。大多數(shù)銷毀操作時(shí)移除強(qiáng)引用的對(duì)象±鞑可以將一個(gè)強(qiáng)引用對(duì)象置為nil來移除它穴豫。
任務(wù) | 方法 | 描述 |
---|---|---|
創(chuàng)建ViewController要使用 的數(shù)據(jù) |
initialization 方法 | 自定義初始化方法 (無論是用init命名還是其他名字), 它的職責(zé)就是將你的視圖控制器置于 一個(gè)可用的良好狀態(tài)。使用這些方法創(chuàng)建 相應(yīng)的數(shù)據(jù)結(jié)構(gòu)精肃,以供對(duì)應(yīng)的操作使用秤涩。 |
分配或者加載視圖所使用的數(shù)據(jù) | ViewDidLoad | 使用ViewDidLoad方法加載你打算展示的 數(shù)據(jù)。該方法調(diào)用時(shí)司抱,你的視圖對(duì)象已經(jīng) 存在并且是可用狀態(tài)筐眷。 |
響應(yīng)系統(tǒng)低內(nèi)存的通知 | didReceiveMemoryWaring | 使用此對(duì)象銷毀ViewController中 非關(guān)鍵的數(shù)據(jù),盡可能的銷毀更對(duì)的數(shù)據(jù) |
視圖ViewController的關(guān)鍵對(duì)象 | dealloc | 重寫該方法僅用于執(zhí)行ViewController 的最后一次清理操作习柠。系統(tǒng)會(huì)自動(dòng)清理掉 實(shí)例變量所存儲(chǔ)的變量和屬性匀谣, 所以你不需要手動(dòng)的釋放。 |