NIB 和 XIB 的区别与联系

NIB 和 XIB 都是 Interface Builder 的图形界面设计文档。引用《Cocoa Programming for Mac OSX》一书的说法,Interface Builder 把窗口、菜单栏以及窗口上的各种控件的对象都“冻结”在了一个 NIB文档里面了;程序运行时,这些对象将会“苏醒”。

在终端下我们可以看到,NIB 其实是一个目录。它里面有两个也是后缀为 NIB 的文件:designable.nib 和 keyedobjects.nib。前者是一个 XML 文档,而后者则是一个二进制文件。Interface Builder 3 之后,引入了新的文档格式:XIB。它是单一的 XML 文档,也就是一个纯文本文件。纯文本文件的好处是显而易见的。嗯,就是便于源代码版本管理。现在最新版本的 Xcode 在创建项目时,已经默认使用 XIB 格式的文档了。

不论在 Interface Builder 中选择的是 NIB 还是 XIB 格式,Xcode 编译后都将得到一个供程序运行时使用的经过编译的 NIB 文件。

 

NIB的生命周期

1.It loads the contents of the nib file and any referenced resource files into memory:

The raw data for the entire nib object graph is loaded into memory but is not unarchived.

Any custom image resources associated with the nib file are loaded and added to the Cocoa image cache; see “About Image and Sound Resources.”

Any custom sound resources associated with the nib file are loaded and added to the Cocoa sound cache; see “About Image and Sound Resources.”

2.It unarchives the nib object graph data and instantiates the objects. How it initializes each new object depends on the type of the object and how it was encoded in the archive. The nib-loading code uses the following rules (in order) to determine which initialization method to use.
a. By default, objects receive an initWithCoder: message.

In OS X, the list of standard objects includes the views, cells, menus, and view controllers that are provided by the system and available in the default Xcode library. It also includes any third-party objects that were added to the library using a custom plug-in. Even if you change the class of such an object, Xcode encodes the standard object into the nib file and then tells the archiver to swap in your custom class when the object is unarchived.

In iOS, any object that conforms to the NSCoding protocol is initialized using the initWithCoder: method. This includes all subclasses of UIView and UIViewController whether they are part of the default Xcode library or custom classes you define.

b. Custom views in OS X receive an initWithFrame: message.

Custom views are subclasses of NSView for which Xcode does not have an available implementation. Typically, these are views that you define in your application and use to provide custom visual content. Custom views do not include standard system views (like NSSlider) that are part of the default library or part of an integrated third-party plug-in.

When it encounters a custom view, Xcode encodes a special NSCustomView object into your nib file. The custom view object includes the information it needs to build the real view subclass you specified. At load time, the NSCustomView object sends an alloc and initWithFrame: message to the real view class and then swaps the resulting view object in for itself. The net effect is that the real view object handles subsequent interactions during the nib-loading process.

Custom views in iOS do not use the initWithFrame: method for initialization.

c. Custom objects other than those described in the preceding steps receive an init message.

3. It reestablishes all connections (actions, outlets, and bindings) between objects in the nib file. This includes connections to File’s Owner and other placeholder objects. The approach for establishing connections differs depending on the platform:
• Outlet connections

In OS X, the nib-loading code tries to reconnect outlets using the object’s own methods first. For each outlet, Cocoa looks for a method of the form setOutletName: and calls it if such a method is present. If it cannot find such a method, Cocoa searches the object for an instance variable with the corresponding outlet name and tries to set the value directly. If the instance variable cannot be found, no connection is created.

In OS X v10.5 and later, setting an outlet also generates a key-value observing (KVO) notification for any registered observers. These notifications may occur before all inter-object connections are reestablished and definitely occur before any awakeFromNib methods of the objects have been called. Prior to v10.5, these notifications are not generated. For more information about KVO notifications, see Key-Value Observing Programming Guide.

In iOS, the nib-loading code uses the setValue:forKey: method to reconnect each outlet. That method similarly looks for an appropriate accessor method and falls back on other means when that fails. For more information about how this method sets values, see its description in NSKeyValueCoding Protocol Reference.

Setting an outlet in iOS also generates a KVO notification for any registered observers. These notifications may occur before all inter-object connections are reestablished and definitely occur before any awakeFromNib methods of the objects have been called. For more information about KVO notifications, see Key-Value Observing Programming Guide.


• Action connections

In OS X, the nib-loading code uses the source object’s setTarget: and setAction: methods to establish the connection to the target object. If the target object does not respond to the action method, no connection is created. If the target object is nil, the action is handled by the responder chain.

In iOS, the nib-loading code uses the addTarget:action:forControlEvents: method of the UIControl object to configure the action. If the target is nil, the action is handled by the responder chain.

• Bindings

In OS X, Cocoa uses the bind:toObject:withKeyPath:options: method of the source object to create the connection between it and its target object.

Bindings are not supported in iOS.

4. It sends an awakeFromNib message to the appropriate objects in the nib file that define the matching selector:

• In OS X, this message is sent to any interface objects that define the method. It is also sent to the File’s Owner and any placeholder objects that define it as well.

• In iOS, this message is sent only to the interface objects that were instantiated by the nib-loading code. It is not sent to File’s Owner, First Responder, or any other placeholder objects.

5. It displays any windows whose “Visible at launch time” attribute was enabled in the nib file.