gpt4 book ai didi

ios - awakeFromNib、导出和 Storyboard : is the documentation wrong?

转载 作者:IT王子 更新时间:2023-10-29 07:57:46 32 4
gpt4 key购买 nike

根据NSObject UIKit Additions Reference , outlet 变量应该在调用 awakeFromNib 时设置(强调所有我的):

The nib-loading infrastructure sends an awakeFromNib message to each object recreated from a nib archive, but only after all the objects in the archive have been loaded and initialized. When an object receives an awakeFromNib message, it is guaranteed to have all its outlet and action connections already established.

...

Important: Because the order in which objects are instantiated from an archive is not guaranteed, your initialization methods should not send messages to other objects in the hierarchy. Messages to other objects can be sent safely from within an awakeFromNib method.

Typically, you implement awakeFromNib for objects that require additional set up that cannot be done at design time. For example, you might use this method to customize the default configuration of any controls to match user preferences or the values in other controls. You might also use it to restore individual controls to some previous state of your application.

但是,这与我的测试不符,至少使用 Storyboard是这样。以下测试的结果似乎与文档相矛盾:

  • 在 Xcode 中创建一个新的单 View 应用程序。
  • 将第二个 ViewController 拖到 Storyboard上。
  • 给第一个 ViewController 一个按钮,并从该按钮创建一个显示第二个 ViewController 的模式转场。
  • 为第二个 ViewController 创建一个 ViewController 类文件。
  • 在 Storyboard上的第二个 ViewController 上创建一个标签,并从它创建一个名为 someLabel 的导出到相应的 ViewController 类。
  • 将以下 awakeFromNib 实现添加到第二个 ViewController:

.

- (void) awakeFromNib {
[super awakeFromNib];
if (self.someLabel == nil) {
NSLog(@"someLabel property is nil");
}
else {
NSLog(@"someLabel property is not nil");
}

if (_someLabel == nil) {
NSLog(@"_someLabel is nil");
}
else {
NSLog(@"_someLabel is not nil");
}
}
  • 在模拟器中运行应用程序并点击按钮。

当我这样做时,我观察到以下记录:

2013-07-01 09:24:35.755 test[498:c07] someLabel property is nil
2013-07-01 09:24:35.758 test[498:c07] _someLabel is nil

由于这种行为,当我需要我的 ViewControllers 有一些涉及它们的 socket 的初始化逻辑时,我需要使用像答案 here 中提出的那样的 hack。为了能够使用网点。如果我正确理解了文档,那么我被迫使用这个 hack 的事实是 UIKit 行为中的一个错误,我应该能够将该初始化放在 awakeFromNib 中 并简单地使用 socket ,没有任何黑客攻击。

不过,我在 Internet 上找不到关于此问题的任何其他提及,考虑到(对我而言)这似乎是一个非常重要的功能,这似乎很奇怪。我也从来没有使用过实际的 nib 文件,只使用过 Storyboard ,所以我对此缺乏一些看法,而且关于这些东西的文档非常冗长和困难,以至于作为 iOS 的新手,我不确定我是否理解正确。这是一个真正的 UIKit 错误,还是我以某种方式误解了文档 - 也许这种方法甚至不打算与 Storyboard结合使用?

最佳答案

简答

您的 View Controller 及其 View 层次结构在运行时从单独的 nib 文件加载。

您的 View Controller 首先加载并接收 awakeFromNib当它的 nib 被加载时,但是它的 View 层次结构 nib 还没有被加载,所以在 awakeFromNib您不应该假设已经设置了 View 层次结构的任何导出。

您的 View Controller 收到 viewDidLoad在它的 View 层次结构 nib 被加载之后,所以在 viewDidLoad 中您可以假设所有导出都已设置。

长答案

当 Xcode 构建您的应用程序时,它会编译您的 Storyboard。结果是一个包含 Info.plist 的包(Finder 将其视为文件的文件夹)和一堆 .nib文件。来 self 的一个项目的示例:

:; pwd
/Users/mayoff/Library/<snip>/Pinner.app/Base.lproj/Main.storyboardc
:; ll
total 80
drwxr-xr-x 10 mayoff staff 340 May 11 22:13 ./
drwxr-xr-x 4 mayoff staff 136 May 11 22:13 ../
-rw-r--r-- 1 mayoff staff 1700 May 11 22:13 AccountCollection.nib
-rw-r--r-- 1 mayoff staff 1110 May 11 22:13 AccountEditor.nib
-rw-r--r-- 1 mayoff staff 2999 May 11 22:13 BYZ-38-t0r-view-8bC-Xf-vdC.nib
-rw-r--r-- 1 mayoff staff 439 May 11 22:13 Info.plist
-rw-r--r-- 1 mayoff staff 7621 May 11 22:13 LqH-9K-CeF-view-OwT-Ts-HoG.nib
-rw-r--r-- 1 mayoff staff 6570 May 11 22:13 OZq-QF-pn5-view-xSR-gK-reL.nib
-rw-r--r-- 1 mayoff staff 2473 May 11 22:13 UINavigationController-ZKB-z3-xgf.nib
-rw-r--r-- 1 mayoff staff 847 May 11 22:13 UIPageViewController-ufv-JN-y6U.nib

Info.plist将 Storyboard 中的场景名称映射到相应的 Nib :

:; plutil -p Info.plist 
{
"UIViewControllerIdentifiersToNibNames" => {
"AccountCollection" => "AccountCollection"
"UINavigationController-ZKB-z3-xgf" => "UINavigationController-ZKB-z3-xgf"
"UIPageViewController-ufv-JN-y6U" => "UIPageViewController-ufv-JN-y6U"
"AccountEditor" => "AccountEditor"
}
"UIStoryboardDesignatedEntryPointIdentifier" => "UINavigationController-ZKB-z3-xgf"
"UIStoryboardVersion" => 1
}

只有当场景具有 Storyboard ID、或连接到它的 segue 或它是初始场景时,它才会显示在此列表中。

Info.plist 中的 nib 文件列表包含那些 View Controller 的 View 层次结构。每个 nib 文件都包含其场景的 View Controller 和场景中的任何其他顶级对象,但不包含 View Controller 的 View 或其任何 subview 。

一个单独的 nib 文件包含场景的 View 层次结构。从 View Controller 及其顶层 View 的对象 ID 派生的 View 层次结构 nib 的名称。您可以在 Xcode 的“Identity Inspector”中查看 Storyboard中任何对象的对象 ID。例如,我的“AccountCollection”场景的 View Controller ID 是 BYZ-38-t0r它的 View ID 是 8bC-Xf-vdC ,所以场景的 View 层次结构在文件 BYZ-38-t0r-view-8bC-Xf-vdC.nib 中.场景 nib 文件包含其 View 层次结构 nib 文件的名称:

:; strings - AccountCollection.nib |grep -e '-.*-'
UIPageViewController-ufv-JN-y6U
BYZ-38-t0r-view-8bC-Xf-vdC <---------
UpstreamPlaceholder-5Hn-fK-fqQ
UpstreamPlaceholder-8GL-mk-Rao
q1g-aL-SLo.title

如果一个场景没有 View 层次结构,那么只有一个用于 View Controller 的 nib 文件,而没有单独的用于 View 层次结构的 nib 文件。例如,UIPageViewController场景在 Storyboard中没有 View 层次结构,因此没有对应于 UIPageViewController-ufv-JN-y6U.nib 的 View 层次结构 Nib .

那么这一切与您的问题有什么关系呢?是这样的:当您的应用从“ Storyboard ”加载场景时,它正在加载包含 View Controller (和其他顶部)的 nib 文件级对象)。当 nib 加载程序完成加载该 nib 文件时,它会发送 awakeFromNib它刚刚加载的所有对象。这包括您的 View Controller ,但它包括您的 View ,因为您的 View 不在该 nib 文件中。

稍后,当您的 View Controller 被要求提供其 view 时属性,它加载包含其 View 层次结构的 nib 文件。 View Controller 将自身传递给 -[UINib instantiateWithOwner:options:]作为owner争论。这就是 nib 加载器如何将 View 层次结构中的对象连接到 View Controller 的导出和操作。

当 nib 加载器完成加载 View 层次结构 nib 时,它会发送 awakeFromNib它刚刚加载的所有对象。由于您的 View Controller 不是这些对象之一,因此您的 View Controller 不会收到awakeFromNib。此时消息。

instantiateWithOwner:options:返回, View Controller 给自己发送 viewDidLoad信息。这是您更改 View 层次结构的机会。

关于ios - awakeFromNib、导出和 Storyboard : is the documentation wrong?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17400547/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com