iOS - layoutSubviews、drawRect、awakeFromNib和 loadNibNamed解釋

awakeFromNib

         當.nib文件被加載的時候,會發送一個awakeFromNib的消息到.nib文件中的每個對象,每個對象都可以定義自己的 awakeFromNib函數來響應這個消息,執行一些必要的操作。也就是說通過nib文件創建view對象是執行awakeFromNib 

viewDidLoad

view對象被加載到內存是就會執行viewDidLoad,所以不管通過nib文件還是代碼的方式創建對象都會執行viewDidLoad

layoutSubviews

layoutSubviews方便數據計算,drawRect方便視圖重繪。

layoutSubviews在以下情況下會被調用:

1、init初始化不會觸發layoutSubviews。

2、addSubview會觸發layoutSubviews。

3、設置view的Frame會觸發layoutSubviews,當然前提是frame的值設置前後發生了變化。

4、滾動一個UIScrollView會觸發layoutSubviews。

5、旋轉Screen會觸發父UIView上的layoutSubviews事件。

6、改變一個UIView大小的時候也會觸發父UIView上的layoutSubviews事件。 

7、直接調用setLayoutSubviews。 


drawRect

 drawRect在以下情況下會被調用:

1、如果在UIView初始化時沒有設置rect大小,將直接導致drawRect不被自動調用。drawRect 掉用是在Controller->loadView,?Controller->viewDidLoad?兩方法之後掉用的.所以不用擔心在 控制器中,這些View的drawRect就開始畫了.這樣可以在控制器中設置一些值給View(如果這些View?draw的時候需要用到某些變量 值).

2、該方法在調用sizeToFit後被調用,所以可以先調用sizeToFit計算出size。然後系統自動調用drawRect:方法。

3、通過設置contentMode屬性值爲UIViewContentModeRedraw。那麼將在每次設置或更改frame的時候自動調用drawRect:。

4、直接調用setNeedsDisplay,或者setNeedsDisplayInRect:觸發drawRect:,但是有個前提條件是rect不能爲0。

以上1,2推薦;而3,4不提倡 ? drawRect方法使用注意點:

1、 若使用UIView繪圖,只能在drawRect:方法中獲取相應的contextRef並繪圖。如果在其他方法中獲取將獲取到一個invalidate 的ref並且不能用於畫圖。drawRect:方法不能手動顯示調用,必須通過調用setNeedsDisplay?或 者?setNeedsDisplayInRect,讓系統自動調該方法。

2、若使用calayer繪圖,只能在drawInContext:?中(類似於drawRect)繪製,或者在delegate中的相應方法繪製。同樣也是調用setNeedDisplay等間接調用以上方法

3、若要實時畫圖,不能使用gestureRecognizer,只能使用touchbegan等方法來調用setNeedsDisplay實時刷新屏幕


initWithNibName

initWithNibName這個方法是在controller的類在IB中創建,但是通過Xcode實例化controller的時候用的. 

initWithCoder

initWithCoder 是一個類在IB中創建但在xocde中被實例化時被調用的.比如,通過IB創建一個controller的nib文件,然後在xcode中通過 initWithNibName來實例化這個controller,那麼這個controller的initWithCoder會被調用.或者是一個view的nib文件,類似方法創建時調用initWithCoder 

關於 initWithNibName 和 loadNibNamed 的區別和聯繫

之所以要把這兩者來一起講,我覺的我也有點困惑,到底用那種?其實真正搞清楚了他們之間的差別,就不會這麼迷惘了。因爲這兩個方法,根本就不是一路貨色。 
既然,是要說明這2個方法,那就着重將區別吧。 
但是第一步,還是要羅嗦一下,他們的聯繫:可以使用此方法加載用戶界面(xib文件)到我們的代碼中,這樣,可以通過操作這個加載進來的(xib)對象,來操作xib文件內容。 
下面進入主題,談區別: 
1. ShowViewController的initWithNibName方法 
ShowViewController * showMessage = [[ShowViewController alloc] 
initWithNibName:@"ShowViewController" bundle:nil]; 
self.showViewController = showMessage; 


2.VideoCellController的loadNibNamed方法 
NSArray * nib = [[NSBundle mainBundle] loadNibNamed:@"SaveViewController" 
owner:self options:nil] ; 
self.showViewController = [nib lastObject]; 
[nib objectAtIndex:0]; 


總結: 
只看他們初始化,那可能感覺是一樣的。但是如果,打開分別看xib的關係的時候,才恍然大悟,原來他們的集成類都不一樣。 
1. initWithNibName要加載的xib的類爲我們定義的視圖控制器類 
2.加載方式不同 
initWithNibName方法:是延遲加載,這個View上的控件是 nil 的,只有到 需要顯示時,纔會不是 nil 
loadNibNamed方法:即時加載,用該方法加載的xib對象中的各個元素都已經存在。 
(認真理解這句幫規:when using loadNibNamed:owner:options:, the File's Owner should be NSObject, the main view should be your class type, and all outlets should be hooked up to the view, not the File's Owner.)


initWithCoder和initWithFrame的區別

initWithoder 是當從nib文件中加載對象的時候會調用,比如你的view來自nib那麼就會調用這個view的這個函數。(由框架調用) 
initWithFrame (是由用戶調用,來初始化對象的) 

發佈了47 篇原創文章 · 獲贊 11 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章