類UIViewController,它被稱為檢視控制器,被用來裝入和釋放檢視、管理檢視互動、並且和其他檢視控制器一起協作完成整體的App介面。為了術語一致,後文會直接使用它的英文名:View Controller。
View Controller管理一個檢視層級體系。比如在一個檢視控制器內加入一個按鈕檢視和一個標籤檢視,分別名為button、label,那麼層次系統如下:
ViewController:UIViewController
view:UIView
button:UIButton
label:UILabel複製程式碼
本文引入一個微小的,但是可以和使用者互動的案例,來演示View Controller的檢視管理能力。基於前文提到的腳手架,程式碼如下:
- 介面包括一個按鈕和一個標籤,標籤初始值為0
- 當點選按鈕時,標籤的數字會被累加1
程式碼如下:
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let page = Page1()
self.window!.rootViewController = page
self.window?.makeKeyAndVisible()
return true
}
}
class Page1: UIViewController {
var count = 0
var label : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
label = UILabel()
label.frame = CGRect(x: 100, y: 100, width: 20, height: 50)
label.text = "0"
view.addSubview(label)
let button = UIButton(type: .system)
button.frame = CGRect(x: 120, y: 100, width: 20, height: 50)
button.setTitle("+",for: .normal)
button.addTarget(self, action: #selector(Page1.buttonAction(_:)), for: .touchUpInside)
view.addSubview(button)
}
func buttonAction(_ sender:UIButton!){
self.count += 1
label.text = self.count.description
}
}複製程式碼
編譯執行後會看到介面上的按鈕和標籤,點選按鈕標籤的值加1,說明App滿足我們的最初需求。
程式碼解釋下:
- UIViewController類內屬性view可以把其他view加入其內
- 按鈕的類為UIButton ,可以通過屬性frame設定位置和大小,可以通過UIViewController.view物件的方法addSubview把按鈕加入到UIViewController內
- 標籤的類為UILabel,可以通過屬性frame設定位置和大小,可以通過UIViewController.view物件的方法addSubview把按鈕加入到UIViewController內
button可以新增事件,通過方法:
button.addTarget(self, action: #selector(Page1.buttonAction(_:)), for: UIControlEvents.touchUpInside)複製程式碼
View Controller內部根據管理的物件的不同,分為兩種:
- Content View Controller ,內容型
- Container View Controller,容器型
兩者的不同之處在於:Container View Controller不但可以管理層次化檢視,還可以管理其他的View Controller,從中取得部分檢視來嵌入自己的整體介面。Container View Controller需要設定嵌入檢視的位置和大小,而原本所在的View Controller管理檢視的內容和事件。
Container View Controller存在的目的是為了更好的做View Controller之間的導航,比如UINavigationController, UITabBarController就是典型的Container View Controller。
如下案例演示一個View Controller作為Container View Controller嵌入另外一個View Controller到自己的使用者介面內:
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window!.rootViewController = Page1()
self.window?.makeKeyAndVisible()
return true
}
}
class Page1: UIViewController{
var c : UIButton!
override func viewDidLoad() {
super.viewDidLoad()
c = UIButton()
c.setTitle("Page1",for: .normal)
c.frame = CGRect(x: 10, y: 50, width: 200, height: 50)
view.addSubview(c)
c.backgroundColor = .blue
let page2 = Page2()
self.addChildViewController(page2)
page2.view.frame = CGRect(x: 10, y: 100, width: 200, height: 50)
view.addSubview(page2.view)
}
}
class Page2: UIViewController{
var c : UIButton!
var count = 0
override func viewDidLoad() {
super.viewDidLoad()
c = UIButton()
c.backgroundColor = .red
c.frame = CGRect(x: 0, y: 0, width: 200, height: 50)
c.setTitle("0",for: .normal)
c.addTarget(self, action: #selector(buttonAction(_:)), for: .touchUpInside)
view.addSubview(c)
}
func buttonAction(_ sender:UIButton!){
self.count += 1
c.setTitle(self.count.description,for: .normal)
}
}複製程式碼
本案例涉及到2個View Controller類,分別為Page1、Page2。Page2中有一個按鈕,點選時會給按鈕的標題的數字加1。而Page1作為Root View Controller,嵌入到Window內,佔據全部螢幕大小,它內嵌一個按鈕和Page2——也就是另外一個View Controller。為了讓Page2的檢視可以顯示在Page1內,需要把Page2.view屬性作為子檢視加入到Page1.view內,並且通過:
self.addChildViewController(page2)複製程式碼
把Page2作為Page1的Child View Controller,這樣就可以重用Page2的已有的邏輯。
作為好奇的程式設計師,不妨試試刪除這一行程式碼,你會發現在點選Page2的按鈕時,數字不會增加,因此說明當此程式碼行被刪除,因此兩個View Controller並沒有任何關係時,它的操作程式碼不能被執行到。
一般很少直接使用UIViewController,更多的是直接使用特定目的的View Controller,也就是UIViewController的子類。常用的特定目的的類有這些:
- AlertController,警示框控制器
- NavigationController,導航控制器
- PageViewController,分頁控制器
- TabBarController,標籤頁控制器
後文會繼續介紹。