UIAlertView, NSURLConnection and wait_fences
-
20-06-2021 - |
Question
I'm trying to display a UIAlertView
with UIActivityIndicator
after a user presses "log in" in a modal view controller. To log in, the credentials are sent to a server using sendAsynchronousRequest:queue:completionHandler:
from the NSURLConnection
class. My implementation is as follows:
UIAlertView * spinner = [[UIAlertView alloc] initWithTitle:@"Connecting to server..." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil];
[spinner show];
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
indicator.center = CGPointMake(spinner.bounds.size.width * 0.5f, spinner.bounds.size.height * 0.5f+5.0f);
[indicator startAnimating];
[spinner addSubview:indicator];
[indicator release];
[NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * res, NSData * data, NSError * err) {
[spinner dismissWithClickedButtonIndex:0 animated:YES];
[spinner release];
...
}
This seems to work fine if the server can't be reached or the server is slow, but if the server replies immediatly, the spinner doesn't seem to be dismissed until after 3-5 seconds with the console logging
wait_fences: failed to receive reply: 10004003
I think this happens because I'm dismissing a modal view controller (the log in screen) while the UIAlertView
is still showing but I'm not sure why this happens as it should normally be dismissed. Am I doing something wrong and what would be the correct way of doing this?
La solution
I have seen this log several times - it is always caused by an unexpected state in the internal animation framework or a collision between default view animations.
Possible reasons:
- Starting animations from inside
viewDidLoad
,viewWillAppear
or similar method - before the view is actually displayed. - Showing/Hiding a
UIAlertView
when anotherUIAlertView
animation is still running. This includes showing an alert fromalertView:didDismissWithButtonIndex:
. - Collision between modal view animation and alert animation.
- Collision between
UINavigationController
push/pop animation and alert animation.
Your case: You are probably hiding your alert even before it has been fully displayed and you get a collision between the two animations. The showing animation takes usually about 0.4 seconds but your response can arrive much earlier - triggering the hiding animation.
Possible solution:
- Trigger request when your animation ends (
didPresentAlertView
). - Measure the duration of your connection and if it`s shorter than 0.4 secs, delay the hiding animation.
Autres conseils
You shouldn't do animations if the View Controller on which that animation is taking place did not appear. So no animations in viewDidLoad. Try in viewDidAppear. That's safer. Take a look here.
Hope this helps.
Cheers!