xib和nib都是Interface Builder的圖形界面設計文檔,nib這個名字來自於NeXTSTEP系統,在NeXTSTEP被Apple收購之前,一直使用nib作為Interface Builder的圖形文檔,nib的發展經過了nib2.0,nib3.0,到NeXTSTEP被Apple收購之后,帶有NeXTSTEP標志的nib被換成了xib
與nib不同的是,xib是一個XML格式的純文本文件,而nib是一個二進制文件,xib比nib有個很明顯的好處,就是xib可以很方便地進行diff操作。由於xib是文本文件,所以在版本控制和管理方面比nib更有優勢。然而,不論在 Interface Builder中選擇的是nib還是xib格式,Xcode編譯后都將得到一個供程序運行時使用的經過編譯的二進制nib文件。現在最新版本的Xcode在創建項目時,已經默認使用xib格式的文檔了。
實際上,nib的生成過程就是一個序列化的過程,
nib文件的生成要經歷兩種序列化。
1. IB所用的文檔的序列化,序列化的結果就是這個XML文件。它保存的是所有界面的資源信息和各個對象之間的關系。
2. 編譯時對這個xml文件進行的序列化,序列化的結果是二進制的nib文件。
寫過IBPlugin的人應該知道,所有的控件必須支持initWithCoder和encodeWithCoder的NSCoding規范,這個就是用來被NSKeyedArchiver序列化用的。
編譯時對xml文件做了如下操作
1. 讀取xml文件,生成所有界面對象,生成所有object(即自定義的controller類等),設置好各個obejct之間的聯系(IBAction,IBOutlet)
2. 對這一坨對象進行序列化,即調用encodeWithCoder方法來序列化,生成二進制nib文件為什么要生成二進制文件,因為從二進制文件生成類實例更快一些。
而在程序運行時,對nib文件進行反序列化的過程
運行時對nib的操作
1. 反序列化,調用所有對象的initWithCoder方法
2. 某些類的initWithFrame,init之類的方法被調用,生成所有類實例
3. 發送awakeFromNib消息,每個類實例的awakeFromNib被調用
引用《Cocoa Programming for Mac OSX》一書的說法,Interface Builder 把窗口、菜單欄以及窗口上的各種控件的對象都“凍結”在了一個 NIB文檔里面了;程序運行時,這些對象將會“蘇醒”。
猜測nib2.0/3.0時代的多出來的二進制文件應該就是被編譯序列化之后的文件,即nib2.0/3.0的nib文件由界面信息文件和運行時二進制文件組成。
由以上的可以看出,凡是被拖到nib里面的對象都會被自動創建實例,無需你代碼手動創建(掃盲了。。。),需要用到的話,添加一個IBOutlet即可。
關於nib加載過程,有篇文章已經寫的非常好了,直接引用過來
地址:http://edsioon.me/nib%E6%96%87%E4%BB%B6%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B/
Nib文件是保存由Interface Builder創建的對象及對象間關系的一種資源文檔。Nib文件中的對象包括:接口對象(可視化對象–窗口,視圖,控件,菜單等;非可視化對象–窗口控制器,視圖控制器,程序委托代理等)和占位符對象(File’s Owner,First Responder,Application)。它描述了對象,以及對象間的關系。對象間的關系包括:連接Nib文件的所有者-File’s Owner,屬性實例變量綁定,動作方法綁定和委托綁定。當Nib文件被加載后,接口對象被創建,占位符對象並不會被創建。應該在你的代碼中創建此占位符對象,並把它傳遞給nib的加載代碼。
1、將Nib文件內容與相關資源加載到內存
- 將全部的Nib對象圖(object graph)的原始數據加載到內存,但是數據是序列化(unarchived)的。
- 將所有與Nib文件相關的自定義圖片資源加載到內存,且被添加到Cocoa image cache。
- 將所有與Nib文件相關的聲音資源加載到內存,且被添加到Cocoa sound cache。
2、反序列化Nib對象圖數據,初始化對象。每個新對象如何初始化取決於對象類型以及序列化的方式。
- 通常情況下,對象通過initWithCoder:初始化。在iOS中,任何服從NSCoding協議的對象都通過initWithCoder方法初始化。這包括UIView和UIViewController的所有的子類,無論Xcode庫的默認類還是自定義類。
- OS X中自定義View通過initWithFrame:初始化,但是iOS中不使用此方法初始化自定義類。
- 其他自定義對象,通過init方法進行初始化。
3、重建Nib中對象的所有的聯系(action、outlet),包括與File’s Owner與其他占位對象的聯系
- outlet connections:在iOS中,nib加載代碼利用setValue:forKey:重新連接outlet。在iOS中設置一個outlet會對所有的注冊觀察者發送一個KVO通知,這些通知有可能在所有的對象聯系重建之前發出,並且肯定會發生在對象的任一awakeFromNib被調用之前。
- action connections:在iOS中,nib加載代碼會調用UIControl的addTarget:action:forControlEvents:方法來設置action。如果target參數為nil,action會由responder chain處理。
4、向Nib中相應的對象發送awakeFromNib消息。在iOS中,此消息僅發送給由nib加載代碼初始化的對象,File’s Owner、First Responser、任一占位對象都接收不到awakeFromNib消息。
5、顯示那些可見屬性為YES的對象。
總結:
A. 加載Nib文件->創建對象alloc->初始化init->創建對象間的連接->向創建的對象發送awakeFromNib消息。
B. 在執行初始化init方法期間,所有的IBOutlet實例變量都為nil,只有創建了nib文件中的所有對象(包括窗口、文本編輯框、按鈕…),所有連接才算完成。
C. 一旦建立了所有的連接(即對象地址連接到實例變量),會向所有的對象發送消息awakeFromNib。在awakeFromNib方法中,實例變量已連接,實例變量有效。
參考:http://blog.sina.com.cn/s/blog_6291e42d0102uww2.html