0

I have an app that downloads a picture from a server. I would like to show the progress to the user. I have read about UIProgressView on the apple docs and read many answers on this site but I can't get it to work. Here is my code In my viewDidLoad I have

_profileProgressView.hidden= YES;
_profileProgressView.progress = 0.0;

In my - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response I show the UIProgressView and then get the expected size of the image.

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
      self.profileProgressView.hidden= NO;
      [self.remote_response setLength:0];
      received = 0;
      self.filesize = [NSNumber numberWithLongLong:[response expectedContentLength]];
      NSLog(@"Content Length::%@", self.filesize);
  }

In my - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)d, I calculate the percentage of the image downloaded and then update the progress of the UIProgressView and log the download progress.

 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)d {
        [self.remote_response appendData:d];

        NSNumber *resourceLength = [NSNumber numberWithUnsignedInteger:[self.remote_response length]];
        dispatch_async( dispatch_get_main_queue(), ^ {
              float progress = (_profileProgressView.progress + ([self.filesize floatValue]/[resourceLength floatValue])*100);
              [self.profileProgressView setProgress:progress animated:YES];
              NSLog(@"Downloading %.0f%% complete", _profileProgressView.progress);
        });
   }

When I run this code

  1. The UIProgressView never shows up

  2. The log I get is Downloading 0% complete. I expected to get the log of the image being downloaded.

Also I thought I should alloc and init the UIProgressView in the viewDidDownload, when I do that I get UIProgressView but it does not show the progress and it does not hide after the image is done being downloaded.

nupac
  • 2,459
  • 7
  • 31
  • 56
  • Why are you dispatching to the main queue here? The delegate response is called on the main thread so you don't have to do that. Also, progress is on a scale from 0 to 1.0, so I don't know why you are multiplying by 100. Also, are you dragging it out on the storyboard? Then you don't need to alloc and init. – AdamG Aug 27 '13 at 04:09
  • Check whether the progressView object is nil or not. – Prasad Devadiga Aug 27 '13 at 04:16
  • 1
    Have you done [self.view bringSubviewToFront: _profileProgressView]; ?? @Pandey – Nevil Lad Aug 27 '13 at 04:17
  • @AdamG I did'nt use dispatching at first but when it did'nt work I added it because I saw that somewhere on StackOverflow, did'nt have the multiplication either, saw it in a sample code from apple docs and yes dragging on storyboard – nupac Aug 27 '13 at 04:52
  • @prasaddevadiga No, its not nil. – nupac Aug 27 '13 at 04:55
  • @NNL Tried your suggestion, nothing changed – nupac Aug 27 '13 at 04:55
  • @ChalamphongPandey ok, what log you will get for `Content Length:` is it proper one. – Prasad Devadiga Aug 27 '13 at 05:01
  • yup, this is what I got `Content Length::246` – nupac Aug 27 '13 at 05:02
  • 1
    @ChalamphongPandey Are you pragmatically adding UIPreogressView Then have you done [self.view addSubView _profileProgressView] or If you have placed it in to the xib or Storybaord then did you synthasize (@synthasize )the Progress view ?? – Nevil Lad Aug 27 '13 at 07:10
  • @NNL I added the UIProgressView in the storyboard and I dont think `@syntesize` is necessary anymore unless you modify the getter and setter methods – nupac Aug 27 '13 at 07:32

2 Answers2

1

I think you are over complicating the math with boxing and unboxing of datatypes with NSNumber.

What I would do is create three variables:

double fileLength;
double lastProgress;
double currentLength;

Then do simple math:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
  fileLength = [response expectedContentLength];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)d {
  double length = [d length];
  currentLength += length;
  double progress = currentLength/fileLength;

  if (lastProgress < progress) {
    profileProgressView.progress = progress;
    lastProgress = progress;
  }
}
rogchap
  • 933
  • 6
  • 8
  • Using your code I NSLog lastProgress and I get 1.0 instantly. – nupac Aug 27 '13 at 05:16
  • opps...missed a line. length should be [d length] as a double... edited. – rogchap Aug 29 '13 at 02:42
  • I still get the same thing but I think i am having this problem because my image is too small – nupac Aug 29 '13 at 09:05
  • So yup this works, it was the image that was too small. Fetched a slightly bigger image with very slow internet and saw this working. Thanks – nupac Aug 30 '13 at 03:56
0

I too experienced the same issue before. In this case, we couldnt show accurate progress view. In order to show accurate progress, your server should provide the bytes sent in the response headers. Then oly, u can be able to get the exact data in your connection:didReceiveData: delegate. Or else, u 'll get 1.0 instantly.

Even if you want to show progress view in this case without server dependancy, you can achieve it by splitting your data's length into n steps and use NSTimer to progress it.

Mani Kandan
  • 629
  • 4
  • 12