问题描述
我开始对iOS中的NIB / Storyboards机制的低级细节感兴趣。我想更多地了解他们的实现 - 我有兴趣开发自己的机制。我在Apple网站上找到了有关的一些信息。
I became interested in low-level details of NIB/Storyboards mechanisms in iOS. I want to learn more about their implentation - I'm interested in developing of my own mechanism. I found some information about NIB files on the Apple site.
他们说:一个nib文件完全按照Xcode中的配置描述这些对象。在运行时,这些描述用于在应用程序内重新创建对象及其配置。
。好。但我找不到有关如何实现故事板的任何信息。故事板只是一堆(包) NIB
文件 - 每个 UIViewController
一个?或者它使用不同的机制?
那么NIB / Storyboard的 XML
来源呢?是否存在从XML到Objective-C源代码的一些发动机罩内转换器?低级细节将不胜感激。
They said: 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.
. Ok. But I couldn't find any information on how storyboards implemented. Does storyboard is just a bunch (pack) of NIB
files - one for each UIViewController
? Or it use a different mechanism?
And what about the XML
source of NIBs/Storyboards? Are there some underhood translator from XML to Objective-C source code? Low level details will be appreciated.
推荐答案
将Storyboard和XIB文件编译成二进制格式的NIB文件。这些文件是您在部署应用程序时可以在软件包中找到的文件。
Storyboard and XIB files are compiled into binary-format NIB files. These files are what can be found in the bundle when you deploy your application.
NIB文件更易于理解。它们包含一组对象层次结构。故事板更复杂,因为它们包含整个场景,因此包含更多元数据(例如哪个视图控制器是场景中的初始值等)。 Segues也是可解码的对象。
NIB files are simpler to understand. They contain an array of object hierarchies. Storyboards are more complex, as they contain an entire scene, so there is more metadata included (such as which view controller is the initial in the scene, etc.). Segues are also decodable objects.
NIB文件和故事板中定义的每个对象都有一个唯一的密钥(例如 vXZ-lx-hvc
,在编译时,附加了类的名称,因此它最终是 LNViewController-vXZ-lx-hvc
。
Each object defined in NIB files and storyboards have a unique key (such as vXZ-lx-hvc
, which when compiled, have the name of the class appended to it, so it is finally LNViewController-vXZ-lx-hvc
for example).
当您尝试加载在NIB或故事板中定义的对象(通常是视图,视图控制器和segue,以及您可以在Interface Builder中定义的其他对象)时,类型的解码器,负责读取二进制NIB文件中的数据并将其解码为活动对象。然后分配一个对象并调用 initWithCoder:
,传递解码器。然后,该对象为它支持的每个属性调用各种解码方法。例如,表视图将解码其样式,背景视图,单元格高度,委托等等。解码完成后,NIB加载程序调用 awakeFromNib
通知从NIB加载的对象。
When you attempt to load objects defined in a NIB or a storyboard (usually views, view controllers and segues, but also other objects you can define in Interface Builder), a decoder of type UINibDecoder
is created, which is responsible for reading data in the binary NIB file and decoding it into live objects. Then an object is allocated and initWithCoder:
is called, passing the decoder. The object then calls the various decode methods for each property it supports. For instance, a table view would decode, among other things, its style, its background view, its cell height, its delegate, etc. After decoding is complete, the NIB loader calls awakeFromNib
to notify the object it has been loaded from a NIB.
故事板被编译成多个NIB文件,通常是每个视图控制器的NIB文件。从故事板加载对象时,内部 UIStoryboard
具有要为特定视图控制器加载NIB文件的元数据。当视图控制器被解码时(在其 initWithCoder:
中,它将加载其整个视图层次结构,属性值,附加对象等。
Storyboards are compiled into multiple NIB files, usually a NIB file per view controller. When objects are loaded from a storyboard, internally UIStoryboard
has metadata for which NIB file to load for the particular view controller. When the view controller is being decoded (within its initWithCoder:
, it loads its entire view hierarchy, property values, attached objects, etc.
最后,每个NIB文件(以及扩展名为故事板)都能够包含键值信息,该信息在成功解码对象后应用。
Finally, each NIB file (and, by extension, storyboards) is capable of including key-value information, which is applied after the object has been successfully decoded.
要实现您自己的类似系统,您需要提供一个类似的系统,可以推断出类型,分配对象,然后使用您自己的解码器对其进行初始化。由于视图和视图控制器实现了 NSCoding
协议,您可以轻松调查它们支持的密钥,并创建解码器和数据格式以支持相同的密钥。
To implement a similar system of your own, you would need to provide a similar system that can deduce a type, allocate an object, and then initialize it with your own decoder. Since views and view controllers implement the NSCoding
protocol, you could investigate easily what keys they support and create your decoder and data format to support the same keys.
如果您希望遵循NIB和故事板加载流程,我建议查看类转储,设置关键方法的断点并检查传递的参数到方法调用。在64位上调试时模拟器,as sembly输出非常容易阅读,您可以使用 po $ arg1
轻松检查传递的参数,以获取 self
对象, po NSStringFromSelector($ arg2)
用于被调用的方法选择器, po $ arg3
...用于以下参数。
If you wish to follow the NIB and storyboard loading flows, I suggest looking at the class dumps, setting breakpoints for key methods and inspecting passed parameters to method calls. When debugging on the 64-bit simulator, the assembly output is very easy to read, and you can inspect passed parameters easily using po $arg1
for the self
object, po NSStringFromSelector($arg2)
for the called method selector, po $arg3
... for following parameters.
建议的开始方法:
-[UIStoryboard instantiateViewControllerWithIdentifier:]
-[UIStoryboard instantiateInitialViewController]
-[UIStoryboard nibForViewControllerWithIdentifier:]
-[UINibDecoder decodeObjectForKey:]
(和其他 -decode *** ForKey:
方法)
设置一个符号断点并查看传递的程序集和参数。
Set a symbolic breakpoint and look at the assembly and parameters passed.
使用状态恢复时会发生非常类似的过程。不同的是,视图提供了编码器,他们将其属性编码为编码器;在恢复期间,视图从状态恢复解码器恢复。
A very similar process takes place when using state restoration. The difference is, views are provided a coder and they encode their properties to that coder; during restoration, views are restored from the state restoration decoder.
这篇关于iOS故事板/ NIB低级解剖。他们是如何实施的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!