iOS Nib文件與手動編碼初始化區別

從Nib中加載對象實例時,init:或initWithFrame:都不會調用。而是調用initWithNibName initWithCoder:怎麼理解?

1. initWithFrame方法是什麼?

initWithFrame方法用來初始化並返回一個新的視圖對象,根據指定的CGRect(尺寸)。

當然,其他UI對象,也有initWithFrame方法。我們可以以UIView爲例,來搞清楚initWithFrame方法。


2.什麼時候用initWithFrame方法?

簡單的說,我們用手動編碼方式聲明、創建UIView對象時,會使用initWithFrame方法。


3.在此,我們必須搞清楚,初始化UIView的兩種方式。

1.使用 Interface Builder 方式。

這種方式,就是使用nib文件。通常我們說的“拖控件” 的方式。實際編程中,我們如果用Interface Builder 方式創建了UIView對象。那麼,initWithFrame方法方法是不會被調用的。因爲nib文件已經知道如何初始化該View。(因爲,我們在拖該view的時候,就定義好了長、寬、背景等屬性)。

這時候,會調用initWithCoder方法,我們可以用initWithCoder方法來重新定義我們在nib中已經設置的各項屬性。這就是爲什麼使用initWithCoder的原因。

因爲MSKView.xib的view是MSKView類型,而不是UIView類型了,所以其實是從nib中加載對象實例。


2.使用手動編碼方式。

就是我們聲明一個UIView的子類,進行“手工”編寫代碼的方式。

實際編程中,我們使用編程方式下,來創建一個UIView或者創建UIView的子類。這時候,將調用initWithFrame方法,來實例化UIView。

特別注意,如果在子類中重載initWithFrame方法,必須先調用父類的initWithFrame方法。在對自定義的UIView子類進行初始化操作。

比如:

- (id)initWithFrame:(CGRect)frame{

    self = [super initWithFrame:frame];// 先調用父類的initWithFrame方法

    if (self) {

        // 再自定義該類(UIView子類)的初始化操作。

        _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];

        [_scrollView setFrame:CGRectMake(0, 0, 320, 480)];

        _scrollView.contentSize = CGSizeMake(320*3, 480);

        

        [self addSubview:_scrollView];

    }

    return self;

}


當我們所寫的程序裏沒用用Nib文件(XIB)時,用代碼控制視圖內容,需要調用initWithFrame去初始化


- (id)initWithFrame:(CGRect)frame{

    if (self =[superinitWithFrame:frame]) {

        // 初始化代碼

    }

    return self;

}


用於視圖加載nib文件,從nib中加載對象實例時,使用 initWithCoder初始化這些實例對象


- (id)initWithCoder:(NSCoder*)coder{

    if (self =[superinitWithcoder:coder]) {

        // 初始化代碼

    }

    return self;

}


initWithCoder和initWithFrame的區別 :

1.initWithCoder: 對於.xib,當你嵌入一個視圖對象到xib,視圖加載時默認調用的是該方法;例如:假如創建的view來自nib,那麼將會調用initWithCoder,由系統來調用,自己不能調用。

2.initWithFrame: 非.xib的手動編碼,視圖加載時默認調用的是該方法。是由自己調用,來初始化對象的


文檔說明:The init method that gets used depends on how the view is created. It can be explicitly created using initWithFrame or it can be created by loading a nib. In that case, the initWithCoder method gets called when the view is loaded from the nib. There are other init methods for subclasses (like UITableViewController has initWithStyle), so you have to be sure which one is being called. 


4.initWithNibName、initWithCoder、awakeFromNib的區分。

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


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


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


第四、關於initWithNibName 和 loadNibNamed 的區別和聯繫 : 

之所以要把這兩者來一起講,因爲這兩個方法,根本就不是一路貨色,他們的聯繫:可以使用此方法加載用戶界面(xib文件)到我們的代碼中,這樣,可以通過操作這個加載進來的(xib)對象,來操作xib文件內容。 下面進入主題,談區別: 


1. ShowViewController的initWithNibName方法 

ShowViewController  *showMessage = [[ShowViewController alloc] initWithNibName:@"ShowViewController" bundle:nil]; 


2. ShowViewController的loadNibNamed方法 

NSArray  *nib = [[NSBundle mainBundle] loadNibNamed:@“MSKView” owner:self options:nil] ; 


總結: 只看他們初始化,那可能感覺是一樣的。但是如果,打開分別看xib的關係的時候,才恍然大悟,原來他們的集成類都不一樣。


1. initWithNibName要加載的xib的類爲我們定義的視圖控制器類。loadNibNamed要加載的xib的類爲NSOjbect。

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.) 




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章