首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >viewDidLoad在启动时在rootViewController上被调用两次

viewDidLoad在启动时在rootViewController上被调用两次
EN

Stack Overflow用户
提问于 2009-07-03 23:31:35
回答 8查看 25.1K关注 0票数 21

有人知道为什么这个根View Controller's viewDidLoad在启动时会被调用两次吗?快把我逼疯了!

下面是从第一次到viewDidLoad的堆栈跟踪

代码语言:javascript
复制
#0  0x0000276a in -[RootViewController viewDidLoad] at RootViewController.m:71
#1  0x3097548f in -[UIViewController view]
#2  0x00002734 in -[RootViewController initWithCoder:] at RootViewController.m:39
#3  0x30ab5ce4 in -[UIClassSwapper initWithCoder:]
#4  0x30514636 in _decodeObjectBinary
#5  0x30514035 in _decodeObject
#6  0x30ab5a1d in -[UIRuntimeConnection initWithCoder:]
#7  0x30514636 in _decodeObjectBinary
#8  0x30515f27 in -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:]
#9  0x305163b0 in -[NSArray(NSArray) initWithCoder:]
#10 0x30514636 in _decodeObjectBinary
#11 0x30514035 in _decodeObject
#12 0x30ab4dde in -[UINib instantiateWithOptions:owner:loadingResourcesFromBundle:]
#13 0x30ab6eb3 in -[NSBundle(NSBundleAdditions) loadNibNamed:owner:options:]
#14 0x308f85f1 in -[UIApplication _loadMainNibFile]
#15 0x30901a15 in -[UIApplication _runWithURL:sourceBundleID:]
#16 0x308fef33 in -[UIApplication handleEvent:withNewEvent:]
#17 0x308fad82 in -[UIApplication sendEvent:]
#18 0x309013e1 in _UIApplicationHandleEvent
#19 0x32046375 in PurpleEventCallback
#20 0x30245560 in CFRunLoopRunSpecific
#21 0x30244628 in CFRunLoopRunInMode
#22 0x308f930d in -[UIApplication _run]
#23 0x309021ee in UIApplicationMain
#24 0x000022e4 in main at main.m:14

第二次:

代码语言:javascript
复制
#0  0x0000276a in -[RootViewController viewDidLoad] at RootViewController.m:71
#1  0x30ab50cd in -[UINib instantiateWithOptions:owner:loadingResourcesFromBundle:]
#2  0x30ab6eb3 in -[NSBundle(NSBundleAdditions) loadNibNamed:owner:options:]
#3  0x308f85f1 in -[UIApplication _loadMainNibFile]
#4  0x30901a15 in -[UIApplication _runWithURL:sourceBundleID:]
#5  0x308fef33 in -[UIApplication handleEvent:withNewEvent:]
#6  0x308fad82 in -[UIApplication sendEvent:]
#7  0x309013e1 in _UIApplicationHandleEvent
#8  0x32046375 in PurpleEventCallback
#9  0x30245560 in CFRunLoopRunSpecific
#10 0x30244628 in CFRunLoopRunInMode
#11 0x308f930d in -[UIApplication _run]
#12 0x309021ee in UIApplicationMain
#13 0x000022e4 in main at main.m:14
EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2009-07-03 23:41:03

真奇怪。我还没有见过这种特殊的情况,但一般来说,您应该假设viewDidLoad可以被多次调用。每当加载引用该控制器的nib文件时,它都会被调用。

对于一个只有一个笔尖的简单应用来说,这是不应该发生的。但在可以加载和卸载视图控制器的更复杂的应用程序中,这种情况时有发生。

票数 4
EN

Stack Overflow用户

发布于 2011-09-02 03:47:32

当我的应用程序第一次启动时,我也遇到了同样的问题。我发现,在我的MainWindow.xib文件中,我将App Delegate的viewController outlet和Window的rootViewController outlet都设置为根视图控制器。当您在Xcode中构建基于视图的项目文件时,您的应用程序代表的didFinishLaunchingWithOptions将预先填充以下内容:

代码语言:javascript
复制
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;

我相信self.viewController ivar是在didFinishLaunchingWithOptions被调用之前从MainWindow.xib实例化的。然后,上面预先填充的代码设置窗口的rootViewController。因此,如果您在MainWindow.xib文件中为窗口指定了rootViewController插座,那么您的根视图控制器实际上将被创建两次,并被添加为窗口的根视图控制器两次。

票数 16
EN

Stack Overflow用户

发布于 2010-02-06 01:44:53

我做了一些调试,下面是我发现的有关ViewController加载顺序的内容:

代码语言:javascript
复制
initWithNibName:bundle:     self = <original instance>, retainedOutlet = 0x0  
loadView >>>                self = <original instance>, retainedOutlet = 0x0  
      initWithCoder:        self = <coder instance>,    retainedOutlet = 0x0  
      initWithCoder:        self = <coder instance>,    retainedOutlet = 0x0  
      setView:              self = <original instance>, retainedOutlet = 0x0  
      setRetainedOutlet:    self = <original instance>, retainedOutlet = 0x1613c40  
      viewDidLoad           self = <coder instance>,    retainedOutlet = 0x0  
      awakeFromNib          self = <coder instance>,    retainedOutlet = 0x0  
loadView <<<  
viewDidLoad                 self = <original instance>, retainedOutlet = 0x1613c40  
viewWillAppear:             self = <original instance>, retainedOutlet = 0x1613c40  
dealloc                     self = <coder instance>,    retainedOutlet = 0x0
viewDidAppear:              self = <original instance>, retainedOutlet = 0x1613c40

在loadView方法期间,将调用initWithCoder:并创建viewController的新副本。这就是传递到少数方法(如viewDidLoad)中的内容。副本稍后会在dealloc调用中销毁。好消息是,在这个副本中,保留的出口没有配置,所以你可以用它来测试你是否应该初始化变量,调用其他方法,最重要的是,你是否应该在dealloc期间释放和销毁对象。

要点:真正的viewController将配置其保留的IBOutlet属性。如果您在一个被多次调用的被覆盖的方法中,只需检查NULL的一个保留的IBOutlet属性。如果它们是NULL,则立即返回。

有谁知道为什么会这样吗?

这样做的副作用:你不能可靠地使用awakeFromNib

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1081131

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档