views:

1487

answers:

2

Hi, I'm pretty new to iPhone development but I'm close to releasing my first app (related to a website I run). The app requires a very large database and as such I've decided to store only the most commonly used data locally, retrieving the other data via a JSON web service call from the database my website runs off.

Whilst performing OK using the simulator (hitting the live DB) searches relying on the web service call have been taking longer than I'd have hoped they would when running on the phone. These calls look much worse when compared to the native searches which are instantaneous. To reduce the relative difference I wanted to put in a fake interstitial (page with activity indicator) for the native searches (the web service searches already use one) but I've been having an issue with the timing of navigation controller pushes when combined with sleep(n).

Anyway, the search section of my app is a navController wihin a tabController tab. When trying to use code like this:

[[tabBarController.viewControllers objectAtIndex:0] pushViewController:(UIViewController *)waitingController animated:YES];
sleep(2);

I find that the push always waits for the sleep to finish before executing when the effect I want is for the viewcontroller to be pushed and then the app to wait for two seconds before continuing to simulate the search process.

I've had some other weird results with navController pushes, on a few occasions I've experienced what seems to be a mashing of two separate viewcontrollers when the one I've pushed as interstitial remains in place content-wise with only the title of the one I want pushed in it's place remaining.

I'm sure that there is a fundamental lack of understanding on my part to blame so I'm hoping for a bit of guidance here.

Cheers,

Alan.

+1  A: 

sleep(float) blocks the main thread causing the UI to freeze up. You should instead schedule some action to be performed later using -[NSObject performSelector:withObject:afterDelay:]

Example:

[label performSelector:@selector(setText:) withObject:@"Delayed Hello World!" afterDelay:2.0f];
rpetrich
Thanks! This worked perfectly. After getting the data back from the native search I push the waitController (interstitial) and then use performSelector with a delay when calling the method in the appDelegate that loads the results.
alan
A: 

I would look at changing your architecture and not sleeping on the main thread - not a great user experience!

Look into using NSOperation to control your interactions with the web service - this will allow you to queue up operations and have them run in a specific sequence or in parallel.

NSOperation is a very easy way to provide robust threading operations - and you could choose to make a call back to the main thread with any updates you want to do along the way.

I think this architecture will help you make the user interface much better - but once you have reconfigured your thinking to use operations you will find lots of other benefits.

NB: It took me a few times to really get to grips with NSOperation and NSOperationQueue - but the time I invested was definitely worth it.

Grouchal
Thanks for this. I will defn look into NSOperation. Although in this instance my handling of the web service call isn't the issue. I'm trying to replicate the effect I get with the web service call of having an interstitial page when doing the native search. Cheers.
alan
I still think that you should not sleep on the main thread and that this might the cause of your problems - perhaps use NSOperation to manange the timing of the changes in your user interface - even if your operation just sleeps for 2 seconds before sending back a message to your UI to do the next thing - I think it will be better than sleeping on the main thread.
Grouchal
Definitely agree, although I'm making use of performSelector as suggested above which I'm assuming simply delays an action rather than sleeping the thread. (And yes, NSOperation scares me ;) Cheers.
alan