使用Nib創(chuàng)建View Controller

當(dāng)使用可視化方式創(chuàng)建View Controller時,我們通常都是使用Storyboard進行的。我們通常會在同一個Storyboard中創(chuàng)建一大堆的View Controller,這樣又容易導(dǎo)致代碼沖突,因此有時候我們可以考慮直接使用Nib來創(chuàng)建單個View Controller。步驟如下:

步驟一:創(chuàng)建Nib

有兩個方法可以創(chuàng)建這樣的Nib。

方法一:使用Xcode的View Controller模板(推薦)

點擊Command + N創(chuàng)建UIViewController的子類時,選中“Also create XIB file”,Xcode就會自動生成并配置好一個同名的Xib文件,我們直接往里面拖控件、拉線就可以了。


CreateXibFromTemplate.png

方法二:手動創(chuàng)建Xib文件

手動創(chuàng)建Xib文件有點麻煩,但能對Xib的機制有更多的理解。假設(shè)此處的UIViewController的子類名為NibViewController,手動創(chuàng)建的步驟如下:

  1. 點擊Command + N創(chuàng)建一個空白的Xib文件,可以任意命名,但通常來說我們讓它與UIViewController的子類同名,即NibViewController。


    CreateXib.png
  2. 打開這個新建的Xib文件,向其中拖入一個UIView控件。注意,這里拖入的是UIView,而不是UIViewController!
  3. 點擊File's Owner,在Identity inspector中將它的Class設(shè)置為NibViewController,在Collection inspector中將view與剛才拖進來的UIView控件連起來。注意,這里不需要設(shè)置那個UIView控件的class。
FileOwnerConnection.png
FileOwnerIdentify.png

完成上述步驟之后,這個Xib文件就配置好了。接下來按正常流程往上面的UIView控件中添加其他控件、設(shè)置屬性、往NibViewController中拖線就行了。

上面的配置中有個很有意思的一點,那就是設(shè)置“File's Owner”,那“File's Owner”是什么?

  • 設(shè)置Nib的File's Owner,而不設(shè)置UIView的class時,就可以基于Nib創(chuàng)建UIViewController
  • 設(shè)置UIView的class,而不設(shè)置Nib的File's Owner,就是基于Nib創(chuàng)建UIView。

“File's Owner”是什么

Apple官方文檔對“File's Owner”的描述如下:

One of the most important objects in a nib file is the File’s Owner object. Unlike interface objects, the File’s Owner object is a placeholder object that is not created when the nib file is loaded. Instead, you create this object in your code and pass it to the nib-loading code. The reason this object is so important is that it is the main link between your application code and the contents of the nib file. More specifically, it is the controller object that is responsible for the contents of the nib file.

In Xcode, you can create connections between the File’s Owner and the other interface objects in your nib file. When you load the nib file, the nib-loading code recreates these connections using the replacement object you specify. This allows your object to reference objects in the nib file and receive messages from the interface objects automatically.

對于File's Owner,需要記住以下兩點,

  • File's Owner對應(yīng)的是這個方法的owner,Bundle.loadNibNamed(_ name: String, owner: Any?, options: [AnyHashable : Any]? = nil)

  • 當(dāng)nib文件被加載之后,你希望能在代碼中控制它內(nèi)部的控件,可以將某個自定義Class(通常是UIViewController的子類)設(shè)置為這個Nib文件的File's Owner,然后將Nib文件的子控件的Outlet設(shè)置到File's Owner的class中。

對于第二點,大家可能會疑惑,為什么要設(shè)置File's Owner,我們平時都是直接設(shè)置UIView的class的啊?沒錯,當(dāng)我們使用Nib來創(chuàng)建自定義的UIView時,是將這個UIView控件的Class設(shè)置為我們自定義的UIView class類型,但當(dāng)我們要使用Nib來創(chuàng)建自定義的UIViewController時,就必須要設(shè)置File's Owner了,因為這種方式下,我們是將一個UIView控件,而不是UIViewController控件,拖到Nib文件中,作為最底層的superView,然后再UIViewController子類中設(shè)置控件的Outlets,而我們顯然不能將一個UIView控件的class設(shè)置為一個UIViewController子類,這時就只能通過File's Owner來實現(xiàn)了。

步驟二:初始化UIViewController

UIViewController有一個nibName的property,當(dāng)該property不為空時,UIViewController.loadView()會從依據(jù)那個nib文件加載UI。nibName的設(shè)置有以下方式,每種方式都代表了一種初始化NibViewController的方法。

方法一(推薦):UIViewController.init(nibName:bundle:)

使用UIViewController.init(nibName:bundle:)來顯示地指定nibName。

let controller = NibViewController(nibName: "NibViewController", bundle: nil)

方法二:UIViewController.init() + nib文件自動匹配

使用UIViewController.init()時,若iOS能在bundle中根據(jù)view controller的class name匹配到一個nib文件,就會隱式地指定nibName。nib文件的匹配規(guī)則如下:

  • 如果view controller的class name以Controller結(jié)尾,比如NibViewController,那么系統(tǒng)就會匹配不包括Controller的nib文件,即NibView.nib。
  • 系統(tǒng)還會匹配完全同名的nib文件。比如,對于NibViewController,匹配NibViewController.nib。這也是為什么推薦nib文件與view controller同名的原因。
// If the nib file name is NibView.nib or NibViewController.nib
let controller = NibViewController()

方法三:UIViewController.init() + override var nibName: String?

我們還可以通過override``nibName的方式顯示的指定nibName。假如NibViewController對應(yīng)的nib文件是RandomNibName.nib,那么可以使用以下代碼創(chuàng)建NibViewController的實例。

class NibViewController: UIViewController {

    override var nibName: String? {
        return "RandomNibName"
    }

}

let controller = NibViewController()

需要注意的是,當(dāng)我們override var nibName: String?后,即便使用UIViewController.init(nibName:bundle:),也無法修改nibName。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容