Google+ Badge

Wednesday, June 12, 2013

Cancel SVProgressHUD process by tapping on HUD


I am using NSURLConnection to potentially pull a lot of data from the server based on user search criteria. There are times when the user does a pretty board search and getting the results back can take a couple of minutes. It can be a waste of the user's time and server processing especially when the user realizes how much data they are about to get back. I wanted to add a [Cancel] option. Since I already had this working on the Android version I really needed to make it happen on iOS. I looked on the SVProgressHUD site and there was a rather heated discussion about this and how if I was using the HUD to run super long processes then I was doing it all wrong. 

Obviously I beg to differ on that point. I have a potential long running process based on a user request and I show a progress indicator and allow the user to cancel as needed. The code below shows a simple sample but I actually show "Processing record X of Y" in my code so the user gets a feel for how long the process is going to take. I don't know how many records are coming back in the response until I make the request so I can't give a "Are you sure you want to suck down 10meg of data?" message first.

After reading the SVProgressHUD site I investigated some other HUDs to see if they solved my needs but found them to be harder to use or they had other issues once I hooked them up in code. I sniffed around in the SVProgressHUD source code and discovered a solution - Notification Center messages.

Just before I show the HUD I do the following:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(hudTapped:) name:SVProgressHUDDidReceiveTouchEventNotification object:nil];

A sample of showing the HUD which lets the user know how to cancel the operation:

[SVProgressHUD showWithStatus:@"Requesting data...\n(tap to cancel)" maskType:SVProgressHUDMaskTypeBlack];

The method that gets called when HUD is tapped:

- (void)hudTapped:(NSNotification *)notification
{
    NSLog(@"They tapped the HUD");
    // Cancel logic goes here
}

and any time I am done with the HUD, either via tap to cancel or run to completion, I call:

[SVProgressHUD dismiss];
[[NSNotificationCenter defaultCenter] removeObserver:self name:SVProgressHUDDidReceiveTouchEventNotification object:nil];

So far it is working like a champ and appears to be a pretty clean solution. I hope you find uses for my discovery as well. Maybe you want to put in an Easter Egg if they tap it 10 times. Have fun.