Search code examples
iosobjective-cprogress

Animation in progrssView


I use this code to download files. Download animation in progrssView carried out at the last moment. Instead of being implemented during the entire process. How to solve a problem?

Code in my Xcode project:

- (void)viewDidLoad
{
    _progressView = [[UIProgressView alloc] initWithProgressViewStyle: UIProgressViewStyleDefault];
    _progressView.progressTintColor = [UIColor colorWithRed:0.0/255 green:0.0/255 blue:0.0/255 alpha:0.4];
    [[_progressView layer]setFrame:CGRectMake(60, 150, 100, 25)];
    [[_progressView layer]setBorderColor:[UIColor whiteColor].CGColor];
    _progressView.trackTintColor = [UIColor clearColor];
    [_progressView setProgress:(float)(50/100) animated:YES];

    [[_progressView layer]setCornerRadius:_progressView.frame.size.width / 8];
    [[_progressView layer]setBorderWidth:1];
    [[_progressView layer]setMasksToBounds:TRUE];
    _progressView.clipsToBounds = YES;
    [self.view addSubview:_progressView];

    _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    [self.progressView setProgress:0 animated:NO];
}

-(IBAction) downloadButton:(id)sender
{
        if(_downloadTask == nil){
            _url =[NSURL URLWithString:@"http://www.freeiconspng.com/uploads/ios-png-6.png"];
            _url1 =[NSURL URLWithString:@"http://www.freeiconspng.com/uploads/ios-png-6.png"];
            _downloadTask = [_session downloadTaskWithURL:_url];
            _downloadTask = [_session downloadTaskWithURL:_url1];
            [_downloadTask resume];

        }
        else
            [_downloadTask resume];
        }
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location 
{

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"image1.png"];
    BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:NO];

    NSData *urlData = [NSData dataWithContentsOfURL:_url];
    [urlData writeToFile:filePath atomically:YES];

    NSString *filePath1 = [documentsDirectory stringByAppendingPathComponent:@"image2.png"];
    BOOL fileExists1 = [[NSFileManager defaultManager] fileExistsAtPath:filePath1 isDirectory:NO];

    NSData *urlData1 = [NSData dataWithContentsOfURL:_url1];
    [urlData1 writeToFile:filePath1 atomically:YES];
}


- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten  totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;{
dispatch_async(dispatch_get_main_queue(), ^{
[self.progressView setProgress:totalBytesWritten/totalBytesExpectedToWrite animated:YES];
});
}

UPD

You mean it?

dispatch_async(dispatch_get_main_queue(), ^{
_session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

 });

It doesn’t work.

I add label in

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten  totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;{
    dispatch_async(dispatch_get_main_queue(), ^{
    [self.progressView setProgress:totalBytesWritten/totalBytesExpectedToWrite animated:YES];
        _label = [[UILabel alloc]initWithFrame:CGRectMake(91, 15, 500, 50)];
        _label.text = [NSString stringWithFormat: @"%lld", totalBytesWritten];
        _label.numberOfLines = 1;
        _label.backgroundColor = [UIColor blackColor];
        _label.textColor = [UIColor whiteColor];
        _label.textAlignment = NSTextAlignmentCenter;
        [self.view addSubview:_label];


        });  

}

At download time, the numbers in the label increase. After increase number stopped I see progrssView animation.

My label https://drive.google.com/file/d/0B0EJbcHq3ZALX0JNLU1iTFA1d2M/view


Solution

  • The code you've posted looks reasonable. You've implemented the URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: delegate method, which should get called as the data comes in for the file. You're setting the progress view from a call to dispatch_async(dispatch_get_main_queue()), which you should normally do.

    One thing I notice is that you create your NSURLSession configuration using [NSOperationQueue mainQueue], which will cause your NSURLSession delegate methods to be called on an operation queue that runs on the main thread.

    Try passing in nil for the operation queue. You're already protecting your UI code by wrapping it in calls to dispatch_async(dispatch_get_main_queue()) like you should, so the delegate methods should be safe from a background serial queue.

    I would also suggest logging the values of totalBytesWritten and totalBytesExpectedToWrite within your URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: method to figure out how many times it's being called and with what values.

    EDIT

    You show code where you create your NSURLSession from inside a call to dispatch_async:

    dispatch_async(dispatch_get_main_queue(), ^{
    _session = 
      [NSURLSession sessionWithConfiguration:
        [NSURLSessionConfiguration defaultSessionConfiguration] 
        delegate:self 
        delegateQueue:[NSOperationQueue mainQueue]];
     });
    

    That makes no sense whatsoever. What I meant was this:

    _session = 
      [NSURLSession sessionWithConfiguration: 
          [NSURLSessionConfiguration defaultSessionConfiguration] 
        delegate: self 
        delegateQueue: nil];
    

    By passing nil for the delegateQueue parameter, your delegate methods will be called from the background.

    Also adding a new label every time your delegate method gets called is nuts. Simply use NSLog:

    - (void)URLSession:(NSURLSession *)session downloadTask:
        (NSURLSessionDownloadTask *) downloadTask 
      didWriteData:(int64_t) bytesWritten  
      totalBytesWritten:(int64_t)totalBytesWritten 
      totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;
    {
      NSLog(@"In didWriteData, totalBytesWritten = %l, filesize = %l", 
        totalBytesWritten,
        totalBytesExpectedToWrite);
      dispatch_async(dispatch_get_main_queue(), ^
      {
        [self.progressView setProgress:totalBytesWritten/totalBytesExpectedToWrite
          animated:YES];
      }); 
    }