iOS Storyboards/NIBs low-level anatomy. How are they implemented?

前端 未结 2 1768
故里飘歌
故里飘歌 2021-01-30 18:56

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.

2条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-01-30 19:12

    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 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.

    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).

    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.

    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.

    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.

    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.


    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.

    Suggested methods to start with:

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

    (and the other -decode***ForKey: methods)

    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.

提交回复
热议问题