Showing Accurate Progress In UIProgressView While Downloading Images in iphone

后端 未结 4 1927
遥遥无期
遥遥无期 2021-01-03 14:46

I have four urls which consists images... I\'m downloding those images and placing them into documents folder..

here is my code..

相关标签:
4条回答
  • 2021-01-03 14:59

    I'd suggest you use some asynchronous downloading technique (either AFNetworking, SDWebImage, or roll your own with delegate-based NSURLSession) rather than dataWithContentsOfURL so that (a) you don't block the main queue; and (b) you can get progress updates as the downloads proceed.

    I'd also suggest creating a NSProgress for each download. When your delegate method gets updates about how many bytes have been downloaded, update the NSProgress object.

    You then can associate each NSProgress with a observedProgress for a UIProgressView, and when you update your NSProgress, the UI can be updated automatically.

    Or, if you and a single UIProgressView to show the aggregate progress of all of the NSProgress for each download, you can create a parent NSProgress, establish each download's NSProgress as a child of the parent NSProgress, and then, as each download updates its respective NSProgress, this will automatically trigger the calculation of the parent NSProgress. And again, you can tie that parent NSProgress to a master UIProgressView, and you'll automatically update the UI with the total progress, just by having each download update its individual NSProgress.


    There is a trick, though, insofar as some web services will not inform you of the number of bytes to be expected. They'll report an "expected number of bytes" of NSURLResponseUnknownLength, i.e. -1! (There are logical reasons why it does that which are probably beyond the scope of this question.) That obviously makes it hard to calculate what percentage has been downloaded.

    In that case, there are a few approaches:

    1. You can throw up your hands and just use an indeterminate progress indicator;

    2. You can try changing the request such that web service will report meaningful "expected number of bytes" values (e.g. https://stackoverflow.com/a/22352294/1271826); or

    3. You can use an "estimated download size" to estimate the percentage completion. For example, if you know your images are, on average, 100kb each, you can do something like the following to update the NSProgress associated with a particular download:

      if (totalBytesExpectedToWrite >= totalBytesWritten) {
          self.progress.totalUnitCount = totalBytesExpectedToWrite;
      } else {
          if (totalBytesWritten <= 0) {
              self.progress.totalUnitCount = kDefaultImageSize;
          } else {
              double written = (double)totalBytesWritten;
              double percent = tanh(written / (double)kDefaultImageSize);
              self.progress.totalUnitCount = written / percent;
          }
      }
      
      self.progress.completedUnitCount = totalBytesWritten;
      

      This is a bit of sleight of hand that uses the tanh function to return a "percent complete" value that smoothly and asymptotically approaches 100%, using the kDefaultImageSize as the basis for the estimation.

      It's not perfect, but it yields a pretty decent proxy for percent completion.

    0 讨论(0)
  • 2021-01-03 15:03

    Do not use dataWithContentsOfURL, you are blocking the main thread until the data arrives.

    Instead create your own connection with NSURLConnection and start listening to your delegate.

    • connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response: get the total data size with [response expectedContentLength].
    • connection:(NSURLConnection *)connection didReceiveData:(NSData *)data: This is where you do your calculations and update your UIProgressView. Something like, loadedBytes/total data size.

    Good luck.

    0 讨论(0)
  • 2021-01-03 15:07

    Your call to dataWithContentsOfURL is synchronous, meaning you don't get updates as the download is in process.

    You can use a library like AFNetworking (https://github.com/AFNetworking/AFNetworking) which has callbacks to the progress of the download.

    0 讨论(0)
  • 2021-01-03 15:12

    Actually a better solution is to use SDWebImage manager which will load the images in the background for you and cache them. Then the next time you use that image it will check the cache. Google it.

    That way the user also doesn't have to sit around and wait while you're downloading stuff..

    Then look at this other question that has some ideas on how to do a status:

    How to show an activity indicator in SDWebImage

    0 讨论(0)
提交回复
热议问题