Nib/Xib文件的产生,编译和运行本质(待续更新中,感兴趣的请关注)

来源:互联网 发布:看各大报纸软件 编辑:程序博客网 时间:2024/06/05 23:48

虽然大家经常使用IB来进行开发,但可能很多对nib文件的产生,编译和运行本质(好吧,不是nib文件的本质)还不是太了解,虽然平常开发无需了解这些东西,但我想了解下肯定是有好处的,比如svn diff时怎样看出到底有没有改动呢,那么大的一个文件。所以斗胆开贴分享自己对于nib的理解和nib相关的开发的建议,欢迎拍砖。

开说之前对以上的补充几点。
nib的发展经过了nib2.0, nib3.0和xib.。nib2.0(nib文件夹中包含3个文件)和nib3.0(nib文件夹中包含2个文件)的文件结构相差一个二进制文件,且2.0可读性不高,不过已经很少见到这种格式了。如果你发现的你nib还是这种格式,赶紧转换吧,利用IB的Save As….
另外建议工程里面全部使用xib,如果是nib3.0,也赶紧转换吧。因为nib2.0/3.0编译后nib中包含的界面信息不会被去除,程序发布出去后别人可以打开你的nib进行编辑查看的。
xib编译后生成二进制的nib文件,这个是不可打开编辑的,所以不会暴露你的接口什么的信息,而且如果包含二进制文件的话,你的代码管理系统是不能merge or diff的。

感谢simonwang补充
为什么会有这两种奇怪的名字?
nibs这个名字来自于被Apple收购之前的NEXTSTEP系统.在NEXTSTEP被Apple拿下后, Apple给nib文件弄了一种新的基于XML Schema的文件格式,并且把nib的扩展名改为了xib.但是人们仍然习惯于把这种新的格式的文件称为nibs文件.所以我们会感觉nib这个词比较奇怪,实际上道理和我们第一次见到类似”NS…这样子奇怪的名字是一样的,历史遗留而已.

开讲。。。。。。(以下内容是本人自行研究出来的,没有任何官方文档的支持,如无把握,请勿自行修改nib文件,发生任何问题,本人概不负责!)
1)打开IB,新建一个Application的nib,拖一个tab和button进去,保存成sample.xib。如图


2)用textmate打开xib文件(右击选择open with…),收拢所有节点后你会看到一下内容。


从被黄色高亮的部分可以看出xib就是一个标准的xml文件,文件一开始标识出了当前使用的nib版本,即nib2.0/nib3.0/xib,此值不可修改!
另外可以看到很熟悉的字眼key,跟plist很像,但跟其不一样。xib里所有节点的顺序不可被改变,为什么呢?试一下就知道了,改了之后IB不认识了!
当然,谁没事去改变节点的顺序呢。不过可以深入探讨一下为什么不能改变,这样可以了解IB工作的部分原理。
(个人猜测,欢迎讨论)
观察根节点,是archive,Objective-C里什么叫做archive?数据永久化。IB运行时保存的都是object的信息,所以得进行序列化。
做过Java或者C++序列化的应该知道,你是怎么序列化的,那你就得怎么反序列化。
所以这些节点的排列顺序是有道理的。
我相信apple不会傻到直接来解析一个xml文件,xml文件应该是其序列化到文件的某一种反映形式,只要apple愿意,可以把这个文件写成任意形式。
所以拿xml文件的特点来对应nibfile的特点是不行的。当然,nib文件写成xml的格式增加了可读性,但是其很复杂,虽然每一个key都表明了它是干吗的,英语好的也能猜出来,但是其结构还是蛮复杂的,需要上下一一对应才能理解IB中资源对象的数据是什么样的。

被桔黄色高亮的部分应该很容易就看出来是什么。这里有几个值会经常变化。比如team里两个人,一个用的10.5,另一个10.6。10.6创建这个nib,10.5上打开nib看了下,保存。此时虽然没做任何改动,其实IB已经帮你改了,比如SystemVersion,这个就是你系统的build版本,InterfaceBuilderVersion,这个是nibtool的版本,在如AppKitVersion之类的,所以你svn diff时发现只有这些东西变了的话,那就没关系的。

那下面就来单独一个一个来看那些一object开头的节点,看它们到底是干嘛用的。
3-11的内容新手不建议看了,还是等你熟悉了IB和nib之后来看比较有感觉。
3)key=”IBDocument.PluginVersi*****”
见1#
4)key=”IBDocument.EditedObjectIDs”
见2#
5)key=”IBDocument.PluginDependencies”
见1#
6)key=”IBDocument.Metadata”
见3#
7)key=”IBDocument.RootObjects”
见4#
8)key=”IBDocument.Objects”
见5#
9)key=”IBDocument.Classes”
见6#
10)key=”IBDocument.PluginDeclareDevelopmentDependencies”
见7#
11)key=”IBDocument.LastKnownImageSizes”
见8#

上面蓝色字里说到一个词,序列化。
话说一般序列化后不都是二进制文件么,为什么这里是xml格式的。恩,这就要讲到nib文件的编译和运行的原理了。

nib文件从创建,保存,编译到运行要经历两种序列化。
第一个是IB所用的文档的序列化,序列化的结果就是这个xml文件。它保存的是所有界面的资源信息和各个对象之间的关系。
第二个就是编译时对这个xml文件进行的序列化,序列化的结果就是2进制的nib文件。

写过IBPlugin的人应该知道,所有的控件必须支持initWithCoder和encodeWithCoder的NSCoding规范,这个就是用来被NSKeyedArchiver序列化用的。
编译时对xml文件做了如下操作
1,读取xml文件,生成所有界面对象,生成所有object(即自定义的controller类等),设置好各个obejct之间的联系(IBAction,IBOutlet)
2,对这一坨对象进行序列化,即调用encodeWithCoder方法来序列化,生成二进制nib文件
为什么要生成二进制文件,因为从二进制文件生成类实例更快一些。

运行时对nib的操作
1,反序列化,调用所有对象的initWithCoder方法
2,某些类的initWithFrame,init之类的方法被调用,生成所有类实例
3,发送awakeFromNib消息,每个类实例的awakeFromNib被调用

猜测nib2.0/3.0时代的多出来的二进制文件应该就是被编译序列化之后的文件,即nib2.0/3.0的nib文件由界面信息文件和运行时二进制文件组成。

由以上的可以看出,凡是被拖到nib里面的对象都会被自动创建实例,无需你代码手动创建(扫盲了。。。),需要用到的话,添加一个IBOutlet即可。

好了,解析完nib的文件结构之后,应该对IB的工作方式有了一个认识,也对你用IB打开nib后看到的东西的背后的实现方式也应该有了一个清晰的认识。
(iPhone的nib跟Mac没有区别,可以参考)

那么开发过程中,nib有那些需要注意的事项呢?(个人经验)
1)本地化
2)代码管理3)key=”IBDocument.PluginVersi*****”
这个其实跟IBDocument.PluginDependencies是相关的。看图

IB里所有的控件都是由类型为IBPlugin的Plugin提供的。
可以打开IB的Preferences的第二个标签Plug-ins来查看当前注册到IB里的所有plugin。

你只要在你的nib中拖入了某个plugin中所支持的插件,那么你的nib就对这个plugin产生了依赖。
nibtool在编译时会去找IBDocument.PluginDependencies里列出来的plugin来进行链接编译。
所以这两个节点如果产生了变化,那么你的plugin肯定引入了或者删除了某个控件,那界面肯定发生了变化。

4)key=”IBDocument.EditedObjectIDs”

4)key=”IBDocument.EditedObjectIDs”
内容如图

这里的ID代表的是什么东西呢?

在将这一段之前得先交代下IB是怎么唯一定位nib中每一个对象的。

IB中的对象标识有两种。
第一种是在Command+5打开的Identity标签中显示的IB的对每一个对象的表示。如图


它在nib中被objectID来定义。此ID由IB生成且不可修改。只用在IB里定位对象使用,描述nib里对象之间的层次关系(#8有讲)。程序运行时不可能获取到此值。(坛子里记得有个人问能不能获取到此值来做定位的,我当时说的不行,原因在这里。要定位有别的方法,此乃后话。)

第二种是被id来定义的。此id被用在描述程序运行数据之间的引用关系,连接关系(IBAction, IBOutlet),superview, subviews等。(注意跟上面的区别, 上面描述的是你在nib里看到的一层一层的东西,这个描述的是nib被load起来之后各个对象之间的关系)。

这两种id我们下面会见到,这里先交代一下。

那么,这个EditedObjectIDs里的ID代表的是什么呢?
是objectID,不是id。
他应该描述的是所有被编辑过的控件?亦或上次被编辑过的?这里没有做足够的试验,我也不能确定。
不过可以肯定的是,如果svn diff时发现这里变动了,那么界面肯定被修改了。

6)key=”IBDocument.Metadata”
7)key=”IBDocument.RootObjects”
8)key=”IBDocument.Objects”
9)key=”IBDocument.Classes”
10)key=”IBDocument.PluginDeclareDevelopmentDependencies”
11)key=”IBDocument.LastKnownImageSizes”

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 文件。

为什么会有这两种奇怪的名字?
nibs这个名字来自于被Apple收购之前的NEXTSTEP系统.在NEXTSTEP被Apple拿下后, Apple给nib文件弄了一种新的基于XML Schema的文件格式,并且把nib的扩展名改为了xib.但是人们仍然习惯于把这种新的格式的文件称为nibs文件.所以我们会感觉nib这个词比较奇怪,实际上道理和我们第一次见到类似”NS…这样子奇怪的名字是一样的,历史遗留而已.

本文转自:CocoaChina ,文章没有最终完成,但是足以为大家补充相当的知识。

转自:http://www.cocoachina.com/bbs/read.php?tid=18161&page=1


0 0
原创粉丝点击