views:

612

answers:

2

I'm creating a fairly complex iPhone app using Core Data. Up until now, things have been working fine. As the app has been getting more complex, however, a new problem has come up: the first view controller is finishing its viewDidLoad method before the AppDelegate gets even halfway through its applicationDidFinishLaunching method.

The view controller is not the root, which is a tab bar controller. The VC in question is the one for the default selected tab on the tab bar. It's getting instantiated by IB.

Nothing like this has occurred before in my experience, and it's throwing off the important initialization I'm doing in the AppDelegate (getting objects from Core Data and preparing them for use) . Furthermore, it's intermittent -- sometimes the delegate does finish first.

Has anyone else noticed a difficulty like this? Any sample code that deals with such an issue?

I suppose that the answer is to make the VC load the data that the AppDelegate is getting ready only when the AppDelegate sends a message that it's ready. I'm a bit concerned that this is adding something that will just end up biting me in the butt later on.

A: 

Once app delegate initialization is finished, fire an NSNotification — this would be last thing the applicationDidFinishLaunching method will do, presumably.

Have the same app delegate listen for that notification and fire a selector, say loadViewController, which then loads the view controller.

Alex Reynolds
Actually, they would be dispatched immediately. The postNotification method blocks until everyone who subscribes to that notification returns.
Jason Coco
+1  A: 

The solution I'm using to avoid race conditions like this is to completely forego referencing any of the functional UI of the application until the data has been loaded and validated. At the top of my -applicationDidFinishLaunching: method, I do the following:

  1. Create a UIWindow with a subview:
    • a UIImageView of Default.png with a subview:
      • a UIActivityIndicatorView centered in the frame (and animating)
  2. Set window key and visible so the user gets visual feedback as soon as possible that some data crunching is going on before the UI loads.
  3. Do all your data loading and validation (which could include network activity)
  4. Create and add the UI's main view to the window as a subview right below the Default.png view, which then gets faded out and removed from its superview.

How you implement step 4 (subroutine call, asynchronous notification, key-value observation, etc...) is entirely up to you. What's important is the idea of making the loading of any UI components contingent upon the loading of any required data components.

This allows you to write all your UI code without worrying about the data, which is what you want to be doing in an MVC application anyway.

Victorb
I thought something like this would be the answer. Because the data loads very quickly in human terms (just not quickly enough in machine terms), I will probably not do the "wait" screen you are describing, but instead implement step 4 using an NSNotification and have the VC reload its view when it gets notified that the data is ready. Thanks.
mwt