4

I'm trying to show a custom MBProgressHUD while downloading a list of URLs with SDWebImagePrefetcher using NSURLConnection methods.

SDWebImagePrefetcher has a method that, when called, shows in console the progress of the images download.

Now, i would like to show that NSLog progress in the custom MBProgressHUD and I would like the HUD to stay on screen until the process is done, but I don't know how to do it and plus, when my NSURLConnection methods are called, it shows the initial HUD (Connnecting), then quickly jumps to "Complete", even if the images still needs to be downloaded.

Here's my code:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {

    HUD.mode = MBProgressHUDModeDeterminate;

}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {

    HUD.labelText = @"Loading";
    HUD.detailsLabelText = @"Downloading contents..."; //here, i would like to show the progress of the download, but it seems to jump this part
    HUD.dimBackground = YES;

}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

    //arr = array which holds a plist
    NSMutableArray *array = [[[NSMutableArray alloc]init]autorelease];
    for (NSDictionary *dict in arr) {
        for (NSDictionary *val in [dict valueForKey:STR_ROWS]) {
            [array addObject:[val objectForKey:@"image"]];
        }
    }

    [prefetcher prefetchURLs:array];

    HUD.customView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"checkmark.png"]] autorelease];
    HUD.mode = MBProgressHUDModeCustomView;
    HUD.labelText = NSLocalizedString(@"Completed",@"Completed!");
    HUD.detailsLabelText = nil;
    HUD.dimBackground = YES;
    [HUD hide:YES afterDelay:2];

}


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [HUD hide:YES];
    UIAlertView *alertView = [[[UIAlertView alloc] initWithTitle:@"Connection Failed message:[NSString stringWithFormat:@"Connection to the remote server failed with error:\n %@\n Try again in a while"),[error localizedDescription]] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
    [alertView show];
}

I tried to look into the examples, but didn't find out how to do what i want to do.

EDIT

HUD Setup:

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
        if (buttonIndex == 0){
            [alertView dismissWithClickedButtonIndex:0 animated:YES];
        }
        else{
            NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
            switch (internetStatus) {
                case NotReachable:
                {
                    //not reachable
                   break;
                 }
                case (ReachableViaWWAN):
                {
                    //reachable but not with the needed mode
                    break;
                }
                case (ReachableViaWiFi):{
                    HUD = [[MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]retain];
                    HUD.delegate = self;
                    HUD.dimBackground = YES;
                    HUD.labelText = @"Connecting...";
                    NSURL *URL = [NSURL URLWithString:@"http://mywebsite.com/myPlist.plist"];
                    NSURLRequest *request = [NSURLRequest requestWithURL:URL];
                    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
                    [connection start];
                    [connection release];
                    break;
                }

                default:
                    break;
            }

        }
    }

Any ideas?

Phillip
  • 4,276
  • 7
  • 42
  • 74

1 Answers1

4

In connection:didReceiveResponse: you must record how large the download is, for example in self.responseSize. Then, in connection:didReceiveData: you must append the data you just got to the data you previously got, and update the progress:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    HUD.mode = MBProgressHUDModeDeterminate;
    HUD.labelText = @"Loading";
    HUD.detailsLabelText = @"Downloading contents...";
    HUD.dimBackground = YES;

    // Define responseSize somewhere...
    responseSize = [response expectedContentLength];
    myData = [NSMutableData data];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [myData appendData:data];

    HUD.progress = (float)myData.length / responseSize; 
}
Stig Brautaset
  • 2,602
  • 1
  • 22
  • 39
  • Thanks, I tried do it that way, but the problem is that the HUD does not persist on the screen. I think that it may depend on the requested url, i should request all the images url or? – Phillip Sep 19 '12 at 10:03
  • If you request many images and have just the one HUD then you may end up hiding / showing up the HUD over and over and not having time to actually show any progress updates, yes. You need to build an abstraction that handles that. – Stig Brautaset Sep 19 '12 at 13:45
  • Practically I'm fetching and storing the images in cache for later usage, but the process runs in background and may slow down the app, so I wanted to show an HUD for the entire process time and then hide it when done – Phillip Sep 19 '12 at 14:44
  • 2
    Then you need to set up the HUD once for the whole batch, and probably update the progress once for each image that is downloaded. So for image N of TOTAL you update `HUD.progress = (float)N / TOTAL;`. How to apply this at a higher level is left as an exercise for the reader. (Or perhaps a topic for a different question?) – Stig Brautaset Sep 19 '12 at 15:14