概述
在所有擁有UI的系統(tǒng)開發(fā)工作中沈条,一般開發(fā)人員最先認(rèn)識(shí)的都是UI系統(tǒng)酣难,這也是在自然界人們認(rèn)知事物的習(xí)慣-從表及里的認(rèn)知過(guò)程。
從我個(gè)人的經(jīng)驗(yàn)出發(fā)紊撕,包括iOS罢荡,Android,Qt等完成一個(gè)App UI開發(fā)对扶,總結(jié)來(lái)都可以從下圖3個(gè)部分來(lái)完成区赵,那么要系統(tǒng)地掌握一個(gè)系統(tǒng)UI開發(fā)過(guò)程和其中的問(wèn)題,都可以從這3個(gè)方面來(lái)認(rèn)知和展開浪南。
這篇文章笼才,主要探討一下第一部分- view顯示
問(wèn)題和結(jié)論
如圖 view顯示,關(guān)于這個(gè)主題我們需要搞清楚兩件事情(并給出結(jié)論):
- iOS界面顯示到底是什么在顯示络凿?
UIView的層級(jí)結(jié)構(gòu)顯示
- 具體是通過(guò)什么方式顯示
- 通過(guò)UIViewController進(jìn)行UIView管理并顯示
- 通過(guò)代碼
- nib file
- storyboard
- 直接對(duì)UIWindow進(jìn)行addSubView的操作(實(shí)際開發(fā)中不這么做)
解析
問(wèn)題1
我們首先看看顯示一個(gè)簡(jiǎn)單的“hello view”需要做哪些工作骡送。在Xcode中創(chuàng)建一個(gè)Single View Application昂羡,打開Main.storyboard,在右下角的Object Library中拖一個(gè)Label到Main.storyboard的畫布中(靠近左上角放置)各谚,修改Label的文字“hello view”紧憾,運(yùn)行,就會(huì)看到我們想要的界面昌渤。
程序在模擬器中運(yùn)行起來(lái)之后赴穗,在Xcode中選擇Debug View Hierarchy,回看到如下圖的app view 3d渲染: 我們可以看到實(shí)際上組成界面的是UIWindow->UIView->UILabel
因?yàn)閕OS是通過(guò)UIScreen類拿到硬件屏幕顯示,所以事實(shí)上膀息,UIWindow是添加到UIScreen上以最終顯示般眉,所以完整的結(jié)構(gòu)是下圖所示(撒懶網(wǎng)上找得圖哈)
問(wèn)題2
window.addSubView
驗(yàn)證問(wèn)題1所展示的例子,是使用storyboard完成的潜支,在代碼層具體做了些什么甸赃,Interface Builder替我們完成了。這一節(jié)我們來(lái)探究代碼實(shí)現(xiàn)冗酿。
新建一個(gè)Single View Application埠对,打開AppDelegate.swift(OC相應(yīng)代碼很容易參照完成),修改第一個(gè)方法如下代碼示例1:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.mainScreen().bounds)
var text = UILabel(frame: CGRectMake(20, 20, 100, 50))
text.backgroundColor = UIColor.greenColor()
text.text = "Hello World"
window?.addSubview(text)
window?.makeKeyAndVisible()
return true
}
運(yùn)行裁替,結(jié)果如下圖:
可以看到项玛,同樣達(dá)到了顯示一個(gè)UILabel到屏幕上的結(jié)果,我們可以刪除Main.storyboard以證明是我們的代碼得到了這樣的結(jié)果(當(dāng)然這不是必要的)弱判。
查看注釋非常容易理解上面程序做得事:
創(chuàng)建一個(gè)UIWindow占滿整個(gè)UIScreen襟沮,然后創(chuàng)建了一個(gè)UILabel,把它加到UIWindow昌腰,最后把UIWindow設(shè)置為主Window并顯示开伏。
通過(guò)ViewController
通過(guò)代碼
雖然這樣能把UIView顯示在屏幕上,并且也可以構(gòu)建復(fù)雜的View hierarchy遭商,但是這是Apple不推薦的固灵,整個(gè)iOS開發(fā)推薦的管理界面的方法是使用ViewController。
咱們對(duì)上面的代碼進(jìn)行修改劫流,把整個(gè)方法修改為如下代碼示例2:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.mainScreen().bounds)
var text = UILabel(frame: CGRectMake(20, 20, 100, 50))
text.backgroundColor = UIColor.greenColor()
text.text = "Hello World"
var vc = UIViewController()
vc.view.addSubview(text)
window?.rootViewController = vc
window?.makeKeyAndVisible()
return true
}
運(yùn)行程序怎虫,得到和addSubView.png一樣的效果
主要的改動(dòng)就是引入了UIViewController并把ViewController設(shè)置為window.rootViewController,而本來(lái)直接加入window子view的UILabel困介,被UIViewController的View管理起來(lái)
在現(xiàn)實(shí)開發(fā)中大审,ViewController要控制View顯示的方方面面,加載座哩,修改徒扶,布局等等,所以根穷,代碼示例2在這里創(chuàng)建UIViewController并進(jìn)行View的組裝僅僅是為了易于理解姜骡,真正的開發(fā)中导坟,代碼實(shí)現(xiàn)界面顯示會(huì)是如下的做法:
下圖是Xcode Single View Application默認(rèn)的工程結(jié)構(gòu),
打開ViewController.swift圈澈,覆蓋loadView()方法惫周,修改完的代碼示例如下:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func loadView() {
let v = UIView()
self.view = v
let label = UILabel(frame: CGRectMake(20, 20, 100, 50))
label.backgroundColor = UIColor.greenColor()
label.text = "hello world"
v.addSubview(label)
}
}
然后我們得修改AppDelegate的第一個(gè)方法如下代碼示例:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
return true
}
運(yùn)行程序,還是會(huì)得到addSubView.png一樣的效果
除了代碼創(chuàng)建UI外康栈,iOS還提供了兩種方式來(lái)所見(jiàn)即所得地創(chuàng)建UI递递,storyboard和nib file,兩者其實(shí)都是本地化存儲(chǔ)的iOS對(duì)象啥么,在運(yùn)行時(shí)加載組裝和代碼一起完成UI的構(gòu)建和顯示登舞,現(xiàn)在storyboard是Xcode默認(rèn)方式,我們從它看起悬荣。
storyboard
新建一個(gè)Single View Application菠秒,給storyboard中加入一個(gè)UILabel “hello world",然后修改AppDelegate.swift第一個(gè)方法如下代碼示例:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.mainScreen().bounds)
var mainSb = UIStoryboard(name: "Main", bundle: nil)
window?.rootViewController = mainSb.instantiateInitialViewController() as? UIViewController
window?.makeKeyAndVisible()
return true
}
運(yùn)行工程氯迂,會(huì)得到跟沒(méi)有修改AppDelegate.swift之前一樣的結(jié)果践叠。其實(shí),這就是默認(rèn)Single View Application隱性為我們做得事:
加載storyboard,從storyboard中加載initial View Controller嚼蚀,并把initial View Controller設(shè)置為window的rootViewController
nib file
新建一個(gè)Single View Application酵熙,新建一個(gè)User Interface -> View, 命名MainNib,創(chuàng)建完成會(huì)生成一個(gè)MainNib.xib驰坊。選中MainNib.xib,點(diǎn)擊View上面的File’s Owner哮独,然后在右側(cè)Identity Inspector中Custom Class的Class框里填上工程生成的ViewController拳芙。再選擇最右邊的Connection Inspector,將Outlets下面的View拖向畫布(也就是UIView)皮璧,將ViewController的View和MainNib.xib中的View進(jìn)行連接舟扎。拖一個(gè)“Hello World” UILabel到畫布中。
然后修改AppDelegate.swift的第一個(gè)方法為如下代碼:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = ViewController(nibName: "MainNib", bundle: nil)
window?.makeKeyAndVisible()
return true
}
運(yùn)行程序悴务,會(huì)看到和用storyboard相同的結(jié)果睹限。
至此,UI顯示入門就告一段落讯檐。當(dāng)然這里并沒(méi)有深入涉及UIView的相關(guān)內(nèi)容羡疗,這在以后的博客中會(huì)有所涉及。