views:

42

answers:

3
Application Specific Information:
com.oneorangetree.iphoneexample failed to launch in time 
elapsed total CPU time (seconds): 3.500 (user 1.680, system 1.820), 17% CPU 
elapsed application CPU time (seconds): 0.920, 5% CPU

When the app loads, it does ALOT of stuff in viewDidLoad It takes about 30 seconds to complete. How can I put this in a background thread or something to speed up the app and prevent the crash (because it took too long to load)

A: 

Are you overriding "viewDidLoad"? If so, what kind of code are you using?

El Guapo
+1  A: 

Yes, you could use a background thread, however a better approach would be to pre-calculate (or cache) things where possible so the loading time is not as long. What sort of things is your code doing that takes so long to run?

Daniel
Basically Im going to Google Maps and geocoding addresses in your contact book. That takes A LOT of time if you got TONS of contacts. I have 300+ and the app crashes because it takes a long time.
Cocoa Dev
As paxswill has said below using NSOperationQueue you should be able to get this working nicely without too much trouble. If you create an NSOperation subclass that handles the lookup of a single address book entry, then create instances for each of the contacts the NSOperationQueue will take care of all the threading for you. As an added bonus, if (when) an iDevice comes on the scene with more than one core NSOperationQueue will be able to take advantage of it without you having to make a single change to your code :)
Daniel
+1  A: 

I've used NSOperation/NSOperationQueue in the past for simple threading. Specifically, NSInvocationOperation makes it really easy to spin a method call that takes a while off, and NSOperationQueue practically threads it for you. The method you're spawning off has to be thread safe, but that is not particularly hard to do. For example, you could create an NSOperationQueue in your -init or -viewDidLoad methods, and then add the NSInvocationOperation to the queue and send it on it's way.

NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
NSInvocationOperation *lengthyTask = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(processAddresses) object:nil];
[opQueue addOperation:lengthyTask];
[lengthyTask release];

One of the kinda cool things (especially on the desktop) is that on 10.6 (and iOS 4) Grand Central Dispatch is automatically used.

While threading a lengthy task should make your app be more responsive (especially if you watch the results and display them as they come in from the threaded task, maybe with KVO), it would be beneficial to implement some caching. Reloading the address book every launch would be very costly, especially most people don't change their address books a lot. You could store the computed data in a local file or database (Core Data is not too hard to use, and if it's too slow you can use SQLite directly). Then on launch, you can run through the address book, comparing the modification dates on each record from the last time your app was run, geocoding the newly modified records.

paxswill
thank you. This really made the application load significantly faster but is there a way to notify the user that we're still loading data so he/she won't think the app froze?
Cocoa Dev
I'm assume each operation is done sequentially, so you could update the interface as each record is returned. Two ways this could be implemented are with a callback from the threaded task (kinda like a delegate) that updates the interface with an argument. Another way would be to implement [KVC](http://goo.gl/jIBP) on a collection of your data. Have an object observe the collection and process the updates as they come in.Barring that completely, you could try showing a loading message over the screen, kinda like [this](http://goo.gl/ZM7g)
paxswill