我开始对iOS中的NIB / Storyboards机制的低级细节感兴趣。我想更多地了解他们的实施 - 我对开发自己的机制很感兴趣。我在Apple网站上找到了有关NIB files的一些信息。
他们说:a nib file describes these objects exactly as they were configured in Xcode. At runtime, these descriptions are used to recreate the objects and their configuration inside your application.
。好。但我无法找到有关如何实现故事板的任何信息。故事板只是一堆({1}}个NIB
个文件 - 每个UIViewController
一个?或者它使用不同的机制?
那么NIB / Storyboard的XML
来源呢?是否存在从XML到Objective-C源代码的一些发动机转换器?低级细节将不胜感激。
答案 0 :(得分:26)
Storyboard和XIB文件被编译为二进制格式的NIB文件。这些文件是您在部署应用程序时可以在软件包中找到的文件。
NIB文件更易于理解。它们包含一组对象层次结构。故事板更复杂,因为它们包含整个场景,因此包含更多元数据(例如哪个视图控制器是场景中的初始值等)。 Segues也是可解码的对象。
NIB文件和故事板中定义的每个对象都有一个唯一的密钥(例如vXZ-lx-hvc
,在编译时,会附加一个类的名称,所以最后是LNViewController-vXZ-lx-hvc
例如)
当您尝试加载在NIB或故事板中定义的对象(通常是视图,视图控制器和segue,以及您可以在Interface Builder中定义的其他对象)时,会创建类型为UINibDecoder
的解码器,负责读取二进制NIB文件中的数据并将其解码为活动对象。然后分配一个对象并调用initWithCoder:
,通过解码器。然后,该对象为它支持的每个属性调用各种解码方法。例如,表视图将解码其样式,背景视图,单元格高度,委托等等。解码完成后,NIB加载程序调用{{1}}以通知对象从NIB加载。
故事板被编译成多个NIB文件,通常是每个视图控制器的NIB文件。从故事板加载对象时,内部awakeFromNib
具有要为特定视图控制器加载NIB文件的元数据。在解码视图控制器时(在其UIStoryboard
内,它会加载其整个视图层次结构,属性值,附加对象等。
最后,每个NIB文件(以及扩展名为故事板)都能够包含键值信息,该信息在成功解码对象后应用。
要实现您自己的类似系统,您需要提供一个类似的系统,可以推断出类型,分配对象,然后使用您自己的解码器对其进行初始化。由于视图和视图控制器实现了initWithCoder:
协议,因此您可以轻松调查它们支持的密钥,并创建解码器和数据格式以支持相同的密钥。
如果您希望遵循NIB和故事板加载流程,我建议查看类转储,为关键方法设置断点并检查传递的参数到方法调用。在64位模拟器上进行调试时,汇编输出非常易于阅读,您可以使用NSCoding
轻松检查传递的参数,po $arg1
对象,self
用于被调用的方法选择器,po NSStringFromSelector($arg2)
...用于以下参数。
建议的开始方法:
po $arg3
(和其他-[UIStoryboard instantiateViewControllerWithIdentifier:]
-[UIStoryboard instantiateInitialViewController]
-[UIStoryboard nibForViewControllerWithIdentifier:]
-[UINibDecoder decodeObjectForKey:]
方法)
设置符号断点并查看传递的程序集和参数。
使用状态恢复时会发生非常类似的过程。不同的是,视图提供了编码器,他们将其属性编码为编码器;在恢复期间,视图从状态恢复解码器恢复。
答案 1 :(得分:1)
在非常高的层次上(为了掩盖大量的实现细节),Xcode使用Cocoa的本机对象持久性机制(称为NSCoding)序列化您创建的对象图(视图层次结构等)。
NSCoding是一种协议,它允许任何符合它的对象图形序列化并保存到磁盘或通过网络传输,然后重新构建回原始对象图形。
当然还需要存储诸如出口和操作之类的东西,因此除了顶级对象和一堆视图之外,还有更多内容,但您可以将xib文件视为XML您在Xcode中构建的视图层次结构的序列化。