I have a UIBarButtonItem called "Refresh Data". When user clicks it, the app should refresh its data. What happens on that button click is web services are launched and xml data is brought and they are of the order 30000-40000 records. So to prevent UI from hanging i wrote a background thread and did that loading there.
- (void)refreshDataAction
{
NSLog(@"Refresh Data");
//Put up an alert box indicating user to wait while data is loading.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Data is Loading"
message:@"Please wait while data is being refreshed."
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil, nil];
alert.tag = 10;
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSLog(@"hit in clickedbuttonatindex alertview at 259");
self.refreshActIndicator.hidden = NO;
[self.refreshActIndicator startAnimating];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
(unsigned long)NULL), ^(void) {
[self getAllCustomerValues];
NSError *nwerror = nil;
if (![self.secondMOC save:&nwerror])
{
NSLog(@"209 Failed to save second MOC");
}
else
{
//NSLog(@"saved success");
}
});
}
Like you can see alert view shows up. I click OK and the box is still there its "blackened" and its hanging there on the screen. And then 7-8 seconds later the box disappears and the animation starts for activity indicator. My goal is to get something like this. 1.User clicks on the refresh data button. 2.Alert view shows up. 3.User clicks OK. 4.Alert box disappears and immediately the background thread starts working and i see the activity indicator working/animating.
User will know to wait while the activity indicator is animating. So how do i get the app to start animating immediately after user clicks "OK" and the alertview OK not be blackened. Am i clear?If you need more information, please ask. Thanks
EDIT: This screen has a background thread working on it when it loads the first time for that day. There is a screen before this. On it i have continue button and clicking that launches background thread which does exactly the same thing like this one over here.I dont kill it or anything.
EDIT 2:
- (void)refreshDataAction
{
NSLog(@"Refresh Data");
self.txtCustomerSearch.text =@"";
[self cleanUPPreviousLabels];
//Put up an alert box indicating user to wait while data is loading.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Data is Loading"
message:@"Please wait while data is being refreshed."
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil, nil];
//alert.tag = 10;
//[alert show];
[alert performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:FALSE];
NSLog(@"hit in willpresenet alertview at 221");
self.refreshActIndicator.hidden = NO;
[self.refreshActIndicator startAnimating];
NSLog(@"Dispatching");
//Disable the view and all the other controls
self.txtCustomerSearch.userInteractionEnabled =NO;
self.txtCustomerSearch.enabled =NO;
self.btnSearch.enabled =NO;
self.btnSearch.userInteractionEnabled = NO;
self.scrollView.userInteractionEnabled = NO;
//self.view.userInteractionEnabled =NO;
self.chkButton.enabled = NO;
[self deletePreviousValues];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSLog(@"Getting customer values");
[self getAllCustomerValues];
NSLog(@"Got customer values");
NSError *nwerror = nil;
if (![self.secondMOC save:&nwerror])
{
NSLog(@"209 Failed to save second MOC");
}
else
{
//NSLog(@"saved success");
}
self.txtCustomerSearch.userInteractionEnabled = YES;
self.txtCustomerSearch.enabled =YES;
self.btnSearch.enabled =YES;
self.btnSearch.userInteractionEnabled = YES;
self.scrollView.userInteractionEnabled = YES;
self.view.userInteractionEnabled =YES;
self.chkButton.enabled = YES;
[self.refreshActIndicator stopAnimating];
NSLog(@"Saved");
});
NSLog(@"Dispatched");
}
We using MBProgressHUD (https://github.com/jdg/MBProgressHUD) which makes this kind of UI notification easy. Generally you supply a method to be called that can check an atomic BOOL value. Set the BOOL when you put up the HUD, when the background process is complete clear the BOOL and the HUD will automatically go away.
Use
alertView:didDismissWithButtonIndex:
instead ofalertView:clickedButtonAtIndex:
. This way the alert is already dismissed when your code is called.Question - why bother with the alert view? The user knows they tapped a "refresh" icon. You already show an activity indicator, and the alert doesn't give the user a chance to cancel the refresh.
Update: The call to dispatch_async seems a bit off. Try this:
Try changing
to the background priority
It might help to add some NSLogs to see where it is hanging and stop the activity indicator to see if the entire hang happens because of the dispatch.
What is happening is that the main (UI) queue is being stopped for some reason, which causes things to appear to hang. Because it is stopped, things like refresh activity indicators will not animate even if you have told them to start animating. And remember that you cannot update the UI in async so secondMOC should not be used to cause any tables to reload data and [self getAllCustomerValues]; should not do any UI stuff.
You say this is all happening on a background thread - make sure you load the UIAlertView on the main thread:
This will probably fix the problem. Your async call is actually happening on the current thread in the run loop (since it's a background thread), blocking the alert view you're attempting to display (in the same run loop).