【问题标题】:iOS Storyboards/NIBs low-level anatomy. How are they implemented?iOS Storyboards/NIBs 底层剖析。它们是如何实施的?
【发布时间】:2014-04-27 07:47:20
【问题描述】:

我开始对 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.。好的。但我找不到任何关于情节提要如何实现的信息。故事板是否只是一堆(包)NIB 文件 - 每个 UIViewController 一个?或者它使用不同的机制?

那么XML 的 NIB/Storyboard 来源呢?是否有一些从 XML 到 Objective-C 源代码的底层翻译器?低级细节将不胜感激。

【问题讨论】:

  • iOS 应用从不使用 XML,它消耗太多磁盘空间(闪存很昂贵)并且解析速度很慢(尤其是在 ARM 处理器上)。 xib 文件只是源代码,它们总是在构建应用程序时转换为二进制文件。 Mac 应用程序也是如此,尽管它们确实在其他地方使用 XML,因为磁盘空间/性能不是那么重要。这些天我不知道二进制格式是什么。从历史上看,它是 NSCoding。过去 XML 不用于 nib 文件,这会导致源代码控制系统出现问题。 XIB 更容易(尤其是在 Xcode 5 中)管理合并冲突

标签: ios objective-c ios7 storyboard nib


【解决方案1】:

Storyboard 和 XIB 文件被编译成二进制格式的 NIB 文件。当您部署应用程序时,可以在捆绑包中找到这些文件。

NIB 文件更易于理解。它们包含一组对象层次结构。故事板更复杂,因为它们包含整个场景,因此包含更多元数据(例如哪个视图控制器是场景中的初始控制器等)。 Segues 也是可解码的对象。

在 NIB 文件和故事板中定义的每个对象都有一个唯一的键(例如 vXZ-lx-hvc,在编译时会附加类的名称,因此最后是 LNViewController-vXZ-lx-hvc 例如)。

当您尝试加载在 NIB 或故事板中定义的对象(通常是视图、视图控制器和 segue,以及您可以在 Interface Builder 中定义的其他对象)时,会创建一个 UINibDecoder 类型的解码器,它负责用于读取二进制 NIB 文件中的数据并将其解码为活动对象。然后分配一个对象并调用initWithCoder:,通过解码器。然后该对象为它支持的每个属性调用各种解码方法。例如,一个表格视图将解码它的样式、它的背景视图、它的单元格高度、它的委托等。解码完成后,NIB 加载器调用awakeFromNib 来通知它已经加载的对象一个笔尖。

故事板被编译成多个 NIB 文件,通常每个视图控制器一个 NIB 文件。当从情节提要加载对象时,内部UIStoryboard 具有要为特定视图控制器加载哪个 NIB 文件的元数据。当视图控制器被解码时(在其initWithCoder: 内,它会加载其整个视图层次结构、属性值、附加对象等。

最后,每个 NIB 文件(以及扩展的情节提要)都能够包含键值信息,这些信息在对象成功解码后应用。

要实现您自己的类似系统,您需要提供一个类似的系统,该系统可以推断类型、分配对象,然后使用您自己的解码器对其进行初始化。由于视图和视图控制器实现了NSCoding 协议,因此您可以轻松调查它们支持哪些键并创建您的解码器和数据格式以支持相同的键。


如果您希望遵循 NIB 和情节提要加载流程,我建议查看类转储,为关键方法设置断点并检查传递给方法调用的参数。在 64 位模拟器上调试时,汇编输出非常易于阅读,您可以使用 po $arg1 对 self 对象、po NSStringFromSelector($arg2) 对被调用方法选择器、po $arg3 轻松检查传递的参数。 . 用于以下参数。

建议的开始方法:

-[UIStoryboard instantiateViewControllerWithIdentifier:]
-[UIStoryboard instantiateInitialViewController]
-[UIStoryboard nibForViewControllerWithIdentifier:]
-[UINibDecoder decodeObjectForKey:]

(和其他 -decode***ForKey: 方法)

设置符号断点并查看传递的程序集和参数。


使用状态恢复时会发生非常相似的过程。不同之处在于,视图提供了一个编码器,并且它们将其属性编码到该编码器;在恢复过程中,视图从状态恢复解码器中恢复。

【讨论】:

    【解决方案2】:

    在非常高的层次上(掩盖大量实现细节),Xcode 使用 Cocoa 的本地对象持久性机制(称为 NSCoding)序列化您创建的对象图(视图层次结构等)。

    NSCoding 是一种协议,它允许任何符合它的对象图被序列化并保存到磁盘或通过网络传输,然后重新构建回原始对象图。

    当然,出口和动作之类的东西也必须存储,所以它不仅仅是顶级对象和一堆视图,但您可以将 xib 文件视为 XML 序列化您在 Xcode 中构建的视图层次结构。

    【讨论】:

      猜你喜欢
      • 2014-03-09
      • 1970-01-01
      • 2012-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-15
      • 2020-02-20
      • 1970-01-01
      相关资源
      最近更新 更多