ios开发之UIView和UIViewController
UIView 表示屏幕上的一塊矩形區(qū)域,負(fù)責(zé)渲染區(qū)域的內(nèi)容,并且響應(yīng)該區(qū)域內(nèi)發(fā)生的觸摸事件。它在 iOS App 中占有絕對重要的地位,因?yàn)?iOS 中幾乎所有可視化控件都是 UIView 的子類。
UIView 可以負(fù)責(zé)以下幾種任務(wù):
- 繪制和動畫
- 布局和子視圖管理
- 事件處理
繪制和動畫
視圖繪制
UIView 是按需繪制的,當(dāng)整個視圖或者視圖的一部分由于布局變化,變成可見的,系統(tǒng)會要求視圖進(jìn)行繪制。對于那些需要使用 UIKit 或者 CoreGraphics 進(jìn)行自定義繪制的視圖,系統(tǒng)會調(diào)用?drawRect:?方法進(jìn)行繪制。
當(dāng)視圖內(nèi)容發(fā)生變化時,需要調(diào)用?setNeedsDisplay?或者?setNeedsDisplayInRect:?方法,告訴系統(tǒng)該重新繪制這個視圖了。調(diào)用這個方法之后,系統(tǒng)會在下一個繪制周期更新這個視圖的內(nèi)容。由于系統(tǒng)要等到下一個繪制周期才真正進(jìn)行繪制,可以一次性對多個視圖調(diào)用?setNeedsDisplay,它們會同時被更新。
視圖的幾何屬性
視圖有 frame,center,bounds 等幾個基本幾何屬性,其中:
- frame 使用的最多,其坐標(biāo)位置都是相對于父視圖的,可以用于確定本視圖在父視圖中的位置和其自身的大小
- center 的坐標(biāo)位置也是相對于父視圖的,通常用于移動,旋轉(zhuǎn)等動畫操作
- bounds 是相對于自身的,通常情況下就是(0,0,width,height), bounds 的含義可以認(rèn)為是當(dāng)前 view 被允許繪制的范圍
視圖的 ContentMode
視圖在初次繪制完成后,系統(tǒng)會對繪制結(jié)果進(jìn)行快照,之后盡可能地使用快照,避免重新繪制。如果視圖的幾何屬性發(fā)生改變,系統(tǒng)會根據(jù)視圖的 contentMode 來決定如何改變顯示效果。
默認(rèn)的 contentMode 是?UIViewContentModeScaleToFill?,系統(tǒng)會拉伸當(dāng)前的快照,使其符合新的 frame 尺寸。大部分 contentMode 都會對當(dāng)前的快照進(jìn)行拉伸或者移動等操作。如果需要重新繪制,可以把 contentMode 設(shè)置為?UIViewContentModeRedraw,強(qiáng)制視圖在改變大小之類的操作時調(diào)用drawRect:重繪。
動畫
可以以動畫的形式改變視圖的下面這些屬性,只需要告訴系統(tǒng)動畫開始和結(jié)束時的數(shù)值,系統(tǒng)會自動處理中間的過渡過程。
frame bounds center transform alpha backgroundColor contentStretch?
布局和子視圖管理
除了提供視圖本身的內(nèi)容之外,一個視圖也可以表現(xiàn)得像一個容器。當(dāng)一個視圖包含其他視圖時,兩個視圖之間就創(chuàng)建了一個父子關(guān)系。在這個關(guān)系中子視圖被稱為 subView ,父視圖被稱為 superView 。一個視圖可以包含多個子視圖,它們被存放在這個視圖的?subviews?數(shù)組里。添加,刪除,以及操作這些子視圖的相對位置的函數(shù)如下:
addSubview: insertSubview:... bringSubviewToFront: sendSubviewToBack: exchangeSubviewAtIndex:withSubviewAtIndex: removeFromSuperview(子視圖調(diào)用)?
AutoResizing 和 Constraint
當(dāng)一個視圖的大小改變時,它的子視圖的位置和大小也需要相應(yīng)地改變。UIView 支持自動布局,也可以手動對子視圖進(jìn)行布局。
當(dāng)下列這些事件發(fā)生時,需要進(jìn)行布局操作:
- 視圖的 bounds 大小改變#
- 用戶界面旋轉(zhuǎn),通常會導(dǎo)致根視圖控制器的大小改變
- 視圖的 layer 層的 Core Animation sublayers 發(fā)生改變
- 程序調(diào)用視圖的setNeedsLayout或layoutIfNeeded方法
- 程序調(diào)用視圖 layer 的setNeedsLayout方法
Auto Resizing
視圖的autoresizesSubviews屬性決定了在視圖大小發(fā)生變化時,如何自動調(diào)節(jié)子視圖。
可以使用的掩碼如下:
UIViewAutoresizingNone UIViewAutoresizingFlexibleHeight UIViewAutoresizingFlexibleWidth UIViewAutoresizingFlexibleLeftMargin UIViewAutoresizingFlexibleRightMargin UIViewAutoresizingFlexibleBottomMargin UIViewAutoresizingFlexibleTopMargin?
可以通過位運(yùn)算符將它們組合起來,例如?UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth。
Constraint
Constraint 是另一種用于自動布局的方法。本質(zhì)上,Constraint 就是對 UIView 之間兩個屬性的一個約束:
attribute1 == multiplier × attribute2 + constant?
其中方程兩邊不一定是等于關(guān)系,也可以是大于等于之類的關(guān)系。
Constraint 比 AutoResizing 更加靈活和強(qiáng)大,可以實(shí)現(xiàn)復(fù)雜的子視圖布局。
自定義 layout
UIView 當(dāng)中提供了一個?layoutSubviews?函數(shù),UIView 的子類可以重載這個函數(shù),以實(shí)現(xiàn)更加復(fù)雜和精細(xì)的子 View 布局。
蘋果文檔專門強(qiáng)調(diào)了,應(yīng)該只在上面提到的 Autoresizing 和 Constraint 機(jī)制不能實(shí)現(xiàn)所需要的效果時,才使用?layoutSubviews。而且,layoutSubviews 方法只能被系統(tǒng)觸發(fā)調(diào)用,程序員不能手動直接調(diào)用該方法。
那么 layoutSubviews 方法具體調(diào)用的時機(jī)有哪些呢?具體有下面幾種情況:
事件處理
UIView 是 UIResponder 的子類,可以響應(yīng)觸控事件。
通常可以使用?addGestureRecognizer:?添加手勢識別器來響應(yīng)觸控事件,如果需要手動處理,則按需要重載 UIView 中的下面四個函數(shù):
touchesBegan:withEvent: touchesMoved:withEvent: touchesEnded:withEvent: touchesCancelled:withEvent:?
?
UIViewController(視圖控制器),顧名思義,是 MVC 設(shè)計模式中的控制器部分。UIViewController 在 UIKit 中主要功能是用于控制畫面的切換,其中的?view?屬性(UIView 類型)管理整個畫面的外觀。
UIViewController 生命周期
ViewController 生命周期的第一步是初始化。不過具體調(diào)用的方法還有所不同。如果使用 StoryBoard 來創(chuàng)建 ViewController,我們不需要顯式地去初始化,Storyboard 會自動使用?initWithCoder:?進(jìn)行初始化。如果不使用 StoryBoard,我們可以使用?init:?函數(shù)進(jìn)行初始化,init:?函數(shù)在實(shí)現(xiàn)過程中還會調(diào)用?initWithNibName:bundle:。 我們應(yīng)該盡量避免在 VC 外部調(diào)用?initWithNibName:bundle:,而是把它放在 VC 的內(nèi)部(參考這里)。
初始化完成后,VC 的生命周期會經(jīng)過下面幾個函數(shù):
(void)loadView (void)viewDidLoad (void)viewWillAppear (void)viewWillLayoutSubviews (void)viewDidLayoutSubviews (void)viewDidAppear (void)viewWillDisappear (void)viewDidDisappear?
假設(shè)現(xiàn)在有一個 AViewController(簡稱 Avc) 和 BViewController (簡稱 Bvc),通過 navigationController 的 push 實(shí)現(xiàn) Avc 到 Bvc 的跳轉(zhuǎn),下面是各個方法的執(zhí)行執(zhí)行順序:
1. A viewDidLoad 2. A viewWillAppear 3. A viewDidAppear 4. B viewDidLoad 5. A viewWillDisappear 6. B viewWillAppear 7. A viewDidDisappear 8. B viewDidAppear?
如果再從 Bvc 跳回 Avc,會產(chǎn)生下面的執(zhí)行順序:
1. B viewWillDisappear 2. A viewWillAppear 3. B viewDidDisappear 4. A viewDidAppear?
可見 viewDidLoad 只會調(diào)用一次,再第二次跳回 Avc 的時候,AViewController 仍然存在于內(nèi)存中,也就不需要 load 了。
注意上面的生命周期中都沒有提到有關(guān) ViewController 銷毀的內(nèi)容,在 iOS 4 & 5 中 ViewController 中有一個?viewDidUnload?方法。當(dāng)內(nèi)存不足,應(yīng)用收到 Memory warning 時,系統(tǒng)會自動調(diào)用當(dāng)前沒在界面上的 ViewController 的 viewDidUnload 方法。 通常情況下,這些未顯示在界面上的 ViewController 是 UINavigationController Push 棧中未在棧頂?shù)?ViewController,以及 UITabBarViewController 中未顯示的子 ViewController。這些 View Controller 都會在 Memory Warning 事件發(fā)生時,被系統(tǒng)自動調(diào)用 viewDidUnload 方法。
從 iOS 6 開始,viewDidUnload 方法被廢棄掉了,應(yīng)用受到 memory warning 時也不會再調(diào)用 viewDidUnload 方法。我們可以通過重載?- (void)didReceiveMemoryWarning?和?-(void)dealloc?來進(jìn)行清理工作。
轉(zhuǎn)載于:https://www.cnblogs.com/qisi007/p/11073227.html
總結(jié)
以上是生活随笔為你收集整理的ios开发之UIView和UIViewController的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: maven overlay 扩展
- 下一篇: Bag of Tricks for Im