Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Alhazred

macrumors member
Original poster
Jul 5, 2011
35
0
On a view I have a button linked to this method
Code:
- (IBAction)performSearch:(id)sender {
	self.activityIndicator.hidden = FALSE;
	[self.activityIndicator startAnimating];

	NSMutableURLRequest *richiesta = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.sito.it/iosphp/responder.php"]
								cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:120.0];
	[richiesta setHTTPMethod:@"POST"];
	[richiesta setHTTPBody:[[NSString stringWithFormat:@"search=%@", self.textInput.text] dataUsingEncoding:NSASCIIStringEncoding]];
	
	NSURLResponse *response;
	NSError *error;
	NSData *dati = [NSURLConnection sendSynchronousRequest:richiesta returningResponse:&response error:&error];
	
	NSString *esitoRicerca = [[[NSString alloc] initWithData:dati encoding:NSASCIIStringEncoding] autorelease];
	
	[self.activityIndicator stopAnimating];
	self.activityIndicator.hidden = TRUE;
	
	if ([esitoRicerca isEqualToString:@"nodata"]) {
		self.labelEsito.text = @"Nessuna corrispondenza trovata";
	}
	else
	{
		self.labelEsito.text = @"";
		TableResultsViewController *table = [[TableResultsViewController alloc] init];
		table.results = [esitoRicerca JSONValue];
		[self.navigationController pushViewController:table animated:YES];
		[table release];
	}
}
In the php function called by this method I've put a 5 seconds pause to make it slow and see the activity indicator.

When I tap the button I can see the app wait the 5 seconds, but the indicator doesn't appear.

I've tried to remove the lines

[self.activityIndicator stopAnimating];
self.activityIndicator.hidden = TRUE;

going back to the main view the indicator is there spinning.
Why doesn't the indicator start as I tap the button, but after that the php function returns?
 
The answer is probably that this line

Code:
NSData *dati = [NSURLConnection sendSynchronousRequest:richiesta returningResponse:&response error:&error];
is blocking so no UI updates get processed. You should use the asynchronous methods of NSURLConnection instead.
 
The answer is probably that this line

Code:
NSData *dati = [NSURLConnection sendSynchronousRequest:richiesta returningResponse:&response error:&error];
is blocking so no UI updates get processed. You should use the asynchronous methods of NSURLConnection instead.
But if I use an asynchronous request doesn't my method go on pushing the new view before to have the data back from the php function?
If so the table wouldn't have the data to populate the rows.
 
But if I use an asynchronous request doesn't my method go on pushing the new view before to have the data back from the php function?
If so the table wouldn't have the data to populate the rows.

You would do all that in the various asynchronous callbacks.
 
The answer is probably that this line

Code:
NSData *dati = [NSURLConnection sendSynchronousRequest:richiesta returningResponse:&response error:&error];
is blocking so no UI updates get processed. You should use the asynchronous methods of NSURLConnection instead.
It looks that this is not the problem, I've changed the method in this way
Code:
- (IBAction)performSearch:(id)sender {
    self.activityIndicator.hidden = FALSE;
    [self.activityIndicator startAnimating];
    [NSThread sleepForTimeInterval:5.0];
}
the indicator starts after 5 seconds.
Isn't the code executed sequentially?
 
It looks that this is not the problem, I've changed the method in this way
Code:
- (IBAction)performSearch:(id)sender {
    self.activityIndicator.hidden = FALSE;
    [self.activityIndicator startAnimating];
    [NSThread sleepForTimeInterval:5.0];
}
the indicator starts after 5 seconds.
Isn't the code executed sequentially?

Sleeping the main thread is exactly as bad as blocking via a synchronous call. As a rule of thumb you should not do block the run loop running on the main thread ever. If anything is going to take more than a fraction of a second do it in the background or asynchronously.
 
Don't ever write sequential code for UI. The UI (activity indicator, animations, etc.) won't ever update.

Exit your method and the activity indicator will start spinning. Update the UI in another method sometime later (after the data comes back and calls a callback, or, much uglier and less power efficient, using a timer to poll some number of seconds later).
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.