Activity indicator starts not when expected

Discussion in 'iOS Programming' started by Alhazred, Jul 6, 2011.

  1. Alhazred macrumors member

    Joined:
    Jul 5, 2011
    #1
    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?
     
  2. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #2
    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.
     
  3. jnoxx macrumors 65816

    jnoxx

    Joined:
    Dec 29, 2010
    Location:
    Aartselaar // Antwerp // Belgium
    #3
  4. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #4
  5. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #5
  6. Alhazred thread starter macrumors member

    Joined:
    Jul 5, 2011
    #6
    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.
     
  7. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #7
    You would do all that in the various asynchronous callbacks.
     
  8. jnoxx macrumors 65816

    jnoxx

    Joined:
    Dec 29, 2010
    Location:
    Aartselaar // Antwerp // Belgium
    #8
    Excuse me RD!
     
  9. Alhazred thread starter macrumors member

    Joined:
    Jul 5, 2011
    #9
    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?
     
  10. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #10
    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.
     
  11. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #11
    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).
     

Share This Page