詳解 View Controller

類UIViewController,它被稱爲視圖控制器,被用來裝入和釋放視圖、管理視圖交互、而且和其餘視圖控制器一塊兒協做完成總體的App界面。爲了術語一致,後文會直接使用它的英文名:View Controller。javascript

View Controller管理一個視圖層級體系。好比在一個視圖控制器內加入一個按鈕視圖和一個標籤視圖,分別名爲button、label,那麼層次系統以下:java

ViewController:UIViewController
        view:UIView
            button:UIButton
            label:UILabel複製代碼

本文引入一個微小的,可是能夠和用戶交互的案例,來演示View Controller的視圖管理能力。基於前文提到的腳手架,代碼以下:程序員

  1. 界面包括一個按鈕和一個標籤,標籤初始值爲0
  2. 當點擊按鈕時,標籤的數字會被累加1

代碼以下:app

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知足咱們的最初需求。ide

代碼解釋下:spa

  1. UIViewController類內屬性view能夠把其餘view加入其內
  2. 按鈕的類爲UIButton ,能夠經過屬性frame設置位置和大小,能夠經過UIViewController.view對象的方法addSubview把按鈕加入到UIViewController內
  3. 標籤的類爲UILabel,能夠經過屬性frame設置位置和大小,能夠經過UIViewController.view對象的方法addSubview把按鈕加入到UIViewController內
  4. button能夠添加事件,經過方法:code

    button.addTarget(self, action: #selector(Page1.buttonAction(_:)), for: UIControlEvents.touchUpInside)複製代碼

View Controller內部根據管理的對象的不一樣,分爲兩種:orm

  1. Content View Controller ,內容型
  2. 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類,分別爲Page一、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的子類。經常使用的特定目的的類有這些:

  1. AlertController,警示框控制器
  2. NavigationController,導航控制器
  3. PageViewController,分頁控制器
  4. TabBarController,標籤頁控制器

後文會繼續介紹。

相關文章
相關標籤/搜索