viewDidLoad中得到在发射上RootViewController的叫了两声viewDidLo

2019-05-16 17:09发布

任何人都知道为什么这根View Controller's viewDidLoad被发射时调用了两次? 它的驾驶我疯了!

这里是从第一次通过堆栈跟踪viewDidLoad

#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

和第二时间:

#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

Answer 1:

奇怪的。 我还没有看到这种特殊情况,但在一般情况下,你应该假设viewDidLoad中可以多次调用。 每当引用该控制器笔尖文件被加载,它会被调用。

对于一个简单的应用程序只有一个笔尖,这是不应该的。 但是,在一个更复杂的应用程序,可以装载和卸载视图控制器,这一切发生的时间。



Answer 2:

我有同样的问题,当我的应用程序首次启动。 我发现,在我的MainWindow.xib文件,我设置我的两个应用程序委托的viewController出口,我的窗口的rootViewController出口,以我的根视图控制器。 当你在Xcode中创建一个视图根据项目文件,应用程序委托的didFinishLaunchingWithOptions将预先填入:

self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;

我相信self.viewController伊娃从MainWindow.xib中实例化之前didFinishLaunchingWithOptions被调用。 那么,上述预填充代码把窗口rootViewController 。 所以,如果,中联,您指定的rootViewController对Window出口在你的MainWindow.xib文件,你的根视图控制器实际上将两次创建并添加作为窗口的根视图控制器两次。



Answer 3:

我做了一些调试,这里是我的发现对ViewController加载顺序:

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配置的属性。 如果你在越来越多次调用一个重写的方法,只是检查你的保留了一个IBOutlet属性NULL 。 如果是NULL ,则立即返回。

任何人有任何线索,为什么发生这种情况这种方式?

这种副作用:你不能使用awakeFromNib可靠。



Answer 4:

你不能假设的viewDidLoad将只调用一次。 如果你是初始化对象和想要保证执行初始化无论是在init()方法,或者如果您从awakeFromNib方法的榫文件加载。



Answer 5:

我有一个类似的问题,这是我的重命名XIB文件和它的结果ViewController类(文件所有者)。 不这样做 - 因为它确实得到了意见和XML内misdefined代表,它是不可恢复的。 同时,我只好到负载的引用,应该是我新的VC原来的VC。 我认为,造成父重建本身,然后VC,我真的想调用。 基本上,我创建了一个间接递归到具有X2的VC viewDidLoad在我的跟踪条目。

我不认为这是对X2任何正当理由viewDidLoad因为它是一个起源与错误的假设前提条件才能调用其它初始化。 每一个我所见过的X2 viewDidLoad中的时间,这是我的一个编码错误 - 很多时候,当我重构和走动VC类。

如果有比更合理的理由viewDidLoad调用,请某人(苹果开发你在听)解释它的技术细节-我一直在寻找这个问题的答案了几个月。



Answer 6:

我有这个问题,但能够解决它。

解决方案

重命名加载两次视图控制器类。

联系方式

重命名,并做出新的名称全新的东西。 重命名文件不会停止负载两次的问题。 创建一个新的项目(如由他人建议的)可能是矫枉过正,至少首先尝试简单的解决方案! 重命名类目标的VC。

提示 :如果重命名类解决您的问题,那么你显然需要更新到该类所有引用。 您可以通过使用命令+ SHIFT + F为项目范围内的发现加快这。



Answer 7:

我遇到了同样的问题,因为我是重新设计ViewController从头开始摆脱XIB文件,并让类重用。 我有这个第二ViewController这将收到一个实例viewDidLoad消息和一个dealloc的消息。

我发现这是结果loadView方法在不被重新定义ViewController 。 默认loadView称为awakeFromNib ,与nibName属性设置为类的名称。 尽管我已经删除从项目的XIB文件,它仍然在仿真器上的应用程序目录。

因此,即使你可以只重置内容和模拟器的设置,以摆脱第二的viewDidLoad ,更好的方法可能是刚刚重新定义loadView是这样的:

- (void)loadView {
    self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease];
    self.view.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin; 
}

这是有道理的,如果你考虑的文档UIViewController's视图属性:

如果你访问该属性和它的值是目前为零,视图控制器会自动调用loadView方法,并返回结果视图。 默认loadView方法尝试加载从与视图控制器(如果有的话)相关联的笔尖文件的视图。 如果您的视图控制器不具有关联的笔尖文件,你应该重写loadView方法,并用它来创建根视图及其所有子视图。



Answer 8:

就我而言,我没有注意到,其实我已经在分配RootViewController的两倍:

application:didFinishLaunchingWithOptions:applicationDidBecomeActive:



Answer 9:

只需添加到这一点,如果你使用的是系统功能,如TouchID,然后applicationWillResignActive在你的AppDelegate将被调用,如果你是说,控制器复位到安全根控制器,那么你得到重新调用,并performSegueWithIdentifier(self.MAIN_SEGUE ,发件人:自)将不会火!



Answer 10:

这发生在我身上时,我使用xibs构建视图合并项目从故事板的老路上。 切换回的主要原因是事实,我不能妥妥提出了一个模式的看法。 顺便我通常它是由具有从一个UIButton委托方法构造一个特定视图控制器的一个实例中,设置它的一些属性(最进口一个是代表这样我就可以正确地再次关闭该模态视图控制器),然后本的它在模式的方式。 在新的故事板的方式,推测这是具有SEGUE完成。 自定义转换只能通过使扩展了UIStoryboardSegue类的自定义类是可行的。 我觉得这样太麻烦相比,它使用的是简单的方式,使我重新合并。

这是怎么使我有一个视图控制器负载两次? 当传送从故事板项目到项目XIB的代码,我做了几个xibs的(每个视图控制器)和复制从故事板中的ViewController对象。 这导致了在它不是一个VIW一个厦门国际银行,而是一个视图 - 控制; 这意味着我必须把视图 - 控制在一个视图 - 控制(因为文件的所有者也是视图 - 控制的实例)。 我不认为你的情况,你有这个问题,但我希望它或许可以帮助别人的一天。

为了解决这个问题,从移动视图控制器视图出视图控制器和所述对象部分的根级别。 这两个视图控制器,它的导航项目应予以删除。 建立和运行,你可以看到只有一个视图控制器分配。 这是文件的所有者。



文章来源: viewDidLoad getting called twice on rootViewController at launch