Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

viewDidLoad getting called twice on rootViewController at launch

Tags:

Anyone know why this root View Controller's viewDidLoad is being called twice at launch? It's driving me nuts!

here's the stack trace from first time through 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 

and the second time:

#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 
like image 725
Meltemi Avatar asked Jul 03 '09 23:07

Meltemi


People also ask

Can viewDidLoad be called multiple times?

viewDidLoad() is only called once, when the view is loaded from a . storyboard file. viewWillAppear(_:) is called every time the view appears. In this simple app, that means it is only called once.

Is viewDidLoad only called once?

viewDidLoad method is called only once in ViewController lifecycle. The reason retrieveMessage() is called in viewDidLoad because it's adding observer to start listening for received and sent message.

Does viewDidLoad get called before viewWillAppear?

viewWillAppear(_:)Always called after viewDidLoad (for obvious reasons, if you think about it), and just before the view appears on the screen to the user, viewWillAppear is called.

Which is called first viewDidLoad or viewDidAppear?

viewDidLoad is called once when the controller is created and viewDidAppear is called each time the view, well, DID appear. So say you have a modal view that you present, when that view is dismissed, viewDidAppear will be called, and viewDidLoad will not be called.


Video Answer


2 Answers

I had this same issue when my app was first launching. What I found was that in my MainWindow.xib file, I was setting both my App Delegate's viewController outlet, and my Window's rootViewController outlet to my root view controller. When you build a View Based project file in Xcode, your App Delegate's didFinishLaunchingWithOptions will be pre-populated with:

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

I believe that the self.viewController ivar is instantiated from MainWindow.xib before didFinishLaunchingWithOptions gets called. Then the pre-populated code above sets the Window's rootViewController. So if, in conjunction, you specify the rootViewController outlet for the Window in your MainWindow.xib file, your root view controller will actually be created twice and added as the Window's root view controller two times.

like image 175
harrisonlee Avatar answered Oct 01 '22 19:10

harrisonlee


I did some debugging and here's what I found about the ViewController loading order:

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 

During the loadView method, initWithCoder: is called and a new copy of the viewController is created. this is what is passed into a few of the methods (like viewDidLoad). the copy is destroyed later in a dealloc call. the good news is that in this copy, retained outlets are not configured, so you can use this as a test to know if you should initialize variables, call other methods, and most importantly, if you should release and destroy objects during dealloc.

Key takeaway: the real viewController will have its retained IBOutlet properties configured. if you are in an overridden method that is getting called multiple times, just check one of your retained IBOutlet properties for NULL. if they are NULL, then return immediately.

Anybody got any clues as to why this is happening this way?

Side effect of this: you can't use awakeFromNib reliably.

like image 42
FingerTipFun Avatar answered Oct 01 '22 18:10

FingerTipFun