iOS Storyboards/NIB 底层剖析。它们是如何实施的?

2024-01-15

我开始对 iOS 中的 NIB/Storyboards 机制的底层细节感兴趣。我想更多地了解它们的实现 - 我对开发自己的机制感兴趣。我找到了一些关于NIB 文件 https://developer.apple.com/library/mac/documentation/cocoa/conceptual/loadingresources/CocoaNibs/CocoaNibs.html在苹果网站上。

他们说: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?或者它使用不同的机制?

那又如何呢?XMLNIB/故事板的来源?是否有一些从 XML 到 Objective-C 源代码的底层翻译器?低层次的细节将受到赞赏。


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

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

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

当您尝试加载 NIB 或 Storyboard 中定义的对象(通常是视图、视图控制器和 Segues,以及您可以在 Interface Builder 中定义的其他对象)时,类型的解码器UINibDecoder https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/UIKit.framework/UINibDecoder.h创建后,它负责读取二进制 NIB 文件中的数据并将其解码为活动对象。然后分配一个对象并initWithCoder:被调用,传递解码器。然后,该对象为其支持的每个属性调用各种解码方法。例如,表格视图将解码其样式、背景视图、单元格高度、委托等。解码完成后,NIB 加载程序调用awakeFromNib通知对象它已从 NIB 加载。

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

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

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


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

建议从以下方法入手:

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

(和另一个-decode***ForKey:方法)

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


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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS Storyboards/NIB 底层剖析。它们是如何实施的? 的相关文章

  • Objective C (iphone) 关于发布的问题

    如果我创建一个视图 并将其添加为子视图并将其添加到数组中 是否必须释放它两次 UIView cat UIView alloc initWithFrame someFrame self view addSubview cat self ani
  • Google Cloud Messaging 显示成功消息但未发送 iOS

    所以我在使用 Google Cloud Messaging 时遇到了一个非常奇怪的问题 我遇到的问题是它正在成功注册设备 并且当发送消息时我会收到来自 Google 的成功消息 但设备永远不会收到任何消息 我从 GCM 得到的消息是 res
  • iOS WKWebView 处理文件下载

    我面临以下问题 在 Web 界面中 文件下载是通过锚标记触发的 如下所示 a href bla blabla a 虽然 Safari 浏览器可以处理此请求并打开一个对话框来处理文件 但 WKWebView 将此视为普通链接并且不对其执行任何
  • iOS uiwebview 在 WebThread 中崩溃

    我正在寻求一些建议或帮助诊断我所看到的这次崩溃 目前 我认为这可能是一个 webkit 错误 但一切皆有可能 因此请提供您可能有的任何见解 Incident Identifier AEB8EE37 E5D4 4975 97F4 2B2038
  • 如何在 Swift 中使用 CoreBluetooth 更新 BLE 设备的电池电量?

    func peripheral peripheral CBPeripheral didDiscoverCharacteristicsFor service CBService error Error for c in service cha
  • 使用 Interface Builder 创建的自定义视图在其他视图中调用时不会呈现

    我有一个用于主窗口的 xib 并通过以下步骤创建了一个自定义视图 创建一个新类 继承自NSView MyView h import
  • 如何使用 SwiftUI 获取多个屏幕上的键盘高度并移动按钮

    以下代码获取键盘显示时的键盘高度 并将按钮移动键盘高度 在转换源 ContentView 和转换目标 SecibdContentView 处以相同的方式执行此移动 但按钮在转换目标处不移动 如何使按钮在多个屏幕上移动相同 import Sw
  • 如何组合两个 SwiftyJSON 对象

    我有一个 swiftyJSON 对象 例如 location http img http commentCount 0 timestamp 1432460217550 我希望能够向其附加另一个 swiftyJSON 对象 使其看起来像 lo
  • SceneKit unproject Z 文档解释?

    我正在经历一些 SceneKit 概念 而我试图在脑海中巩固的一个概念是 unprojectPoint 我知道该函数将获取 2D 中的一个点并返回 3D 中的一个点 因此具有正确的 Z 值 当我阅读文档时 我读到了以下内容 method u
  • 如何为图层阴影不透明度设置动画?

    我有一个视图 我已将 LayerOpacity 设置为 1 theView layer shadowOpacity 1 0 当视图位于屏幕下方时 这看起来很好 当我将此视图向上移动以与另一个有阴影的视图齐平时 它们看起来不太好 有没有办法让
  • 如何使用 Swift 将“完成”按钮添加到 iOS 中的数字键盘?

    它在默认键盘上工作得很好 但我无法让它在数字键盘上工作 有任何想法吗 据我所知 你不能在键盘部分添加 完成 按钮 你应该添加一个inputAccessoryView to the UITextField or UITextView 如果这就
  • TTTAttributedLabel 可点击截断标记

    我有一个 TTTAttributedLabel 并为其指定了一个自定义属性截断标记 NSAttributedString atributedTruncationToken NSAttributedString alloc initWithS
  • Swift:协议、结构、类

    我开始学习 Swift 语言 但在理解协议 结构和类方面遇到了困难 我来自 Android 方面的编程 所以我相信 Swift 协议基本上是 Java 接口 其中每一个的正确用例是什么 这些类比并不 完全 正确 但这就是我所理解的要点 是的
  • XCode 7 中的 AWSS3TransferManagerUploadRequest

    我今天升级到 Xcode 7 Swift 2 0 我的项目正在使用 CocoaPods 我正在 POD 文件中导入所有与 AWS 相关的文件 我已经设置了桥接标头 并导入了 Amazon 告诉我的所有文件 在升级到 Swift 2 0 之前
  • 如何在Sprite Kit中实现鼠标关节?

    我已经在 iOS 上用 Cocos2d Box2d 编写了拖放功能的工作实现 我需要将它移植到 Sprite Kit 逻辑非常基本 当用户触摸屏幕时 找到手指下的精灵 在找到的精灵和场景的物理体之间创建鼠标关节 将关节的目标设置为触摸位置
  • 检查 Objective-C 块类型?

    这主要是出于好奇 我不太确定它的实际用途是什么 但就这样吧 由于块也是 Objective C 对象 是否可以检查它们的类型 也就是说 它是否响应isKindOfClass 消息以及如何使用该消息来处理块 我天真的以为事情大概是这样的 vo
  • iOS Swift 和 reloadRowsAtIndexPaths 编译错误

    我与 xCode Swift 陷入僵局并刷新 UITableView 的单行 这条线有效 self tableView reloadData 而这条线没有 self tableView reloadRowsAtIndexPaths curr
  • 无需越狱即可检测iOS9上哪个应用程序处于前台

    我正在尝试记录用户在 iOS9 上的个人应用程序使用情况 我宁愿它不会使用越狱有限的解决方案 不言自明 在越狱手机上执行此应用程序的变体应该不难 https www andyibanez com create mobilesubstrate
  • 从plist文件中读取数据

    我正在尝试为我的 iPhone 应用程序实现保存状态 我有一个名为 SaveData plist 的 plist 文件 我可以通过以下方式读取它 NSString pListPath2 bundle pathForResource Save
  • [WebCoreSharedBufferData getBytes:range:]: 范围 {0, 8} 超出数据长度 0'

    我正在更新我的 iOs 7 应用程序 我为 cordova 电话间隙 开发了这个应用程序 当我运行这个应用程序时 我收到错误 FirstDemo 175

随机推荐