Showing the file download progress with NSURLSessionDataTask

前端 未结 4 614
感情败类
感情败类 2020-12-01 06:49

I want to display file download progress (how many bytes are received) of particular file. It works fine with the NSURLSessionDownloadTask .My question is I want to achieve

相关标签:
4条回答
  • 2020-12-01 06:57

    Since iOS 11.0 and macOS 10.13, URLSessionTask (former NSURLSessionTask) adopted the ProgressReporting protocol. That means you can use the progress property to track the progress of a session task.

    Expecting you already know how to use KVO observers, you can do something like:

    task = session.downloadTask(with: url)
    task.resume()
    task.progress.addObserver(self, forKeyPath: "fractionCompleted", options: .new, context: &self.progressKVOContext)
    

    and observe the value with:

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if context == &self.progressKVOContext, let keyPath = keyPath {
            switch keyPath {
            case "fractionCompleted":
                guard let progress = object as? Progress else {
                    return
                }
                DispatchQueue.main.async { [weak self] in
                    self?.onDownloadProgress?(progress.fractionCompleted)
                }
            case "isCancelled":
                cancel()
            default:
                break
            }
        }
        else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }
    

    iOS 13 update

    OperationQueue has now a progress property.

    For example, the UIProgressView can observe that property and update the progress value automatically using the observedProgress. Full example in https://nshipster.com/ios-13/#track-the-progress-of-enqueued-operations.

    0 讨论(0)
  • 2020-12-01 07:13
    import Foundation
    import PlaygroundSupport
    
    let page = PlaygroundPage.current
    page.needsIndefiniteExecution = true
    
    let url = URL(string: "https://source.unsplash.com/random/4000x4000")!
    let task = URLSession.shared.dataTask(with: url) { _, _, _ in
      page.finishExecution()
    }
    
    // Don't forget to invalidate the observation when you don't need it anymore.
    let observation = task.progress.observe(\.fractionCompleted) { progress, _ in
      print(progress.fractionCompleted)
    }
    
    task.resume()
    
    0 讨论(0)
  • 2020-12-01 07:14

    You need to implement following delegates:

    <NSURLSessionDataDelegate, NSURLSessionDelegate, NSURLSessionTaskDelegate>

    Also need to create two properties:

    @property (nonatomic, retain) NSMutableData *dataToDownload;
    @property (nonatomic) float downloadSize;
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
    
        NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
    
        NSURL *url = [NSURL URLWithString: @"your url"];
        NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithURL: url];
    
        [dataTask resume];
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
        completionHandler(NSURLSessionResponseAllow);
    
        progressBar.progress=0.0f;
        _downloadSize=[response expectedContentLength];
        _dataToDownload=[[NSMutableData alloc]init];
    }
    
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
        [_dataToDownload appendData:data];
        progressBar.progress=[ _dataToDownload length ]/_downloadSize;
    }
    
    0 讨论(0)
  • 2020-12-01 07:18

    You can also use NSURLSessionDownloadTask like following. Call startDownload methode.In .h file use this

    - (void)startDownload
    {
        NSString *s;
        s = @"http://www.nasa.gov/sites/default/files/styles/1600x1200_autoletterbox/public/pia17474_1.jpg?itok=4fyEwd02";
        NSURLSessionDownloadTask *task = [self.session downloadTaskWithURL:[NSURL URLWithString:s]];
        [task resume];
    }
    
    - (NSURLSession *) configureSession {
        NSURLSessionConfiguration *config =
        [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.neuburg.matt.ch37backgroundDownload"];
        config.allowsCellularAccess = NO;
        // ... could set config.discretionary here ...
        NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        return session;
    }
    
    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
        CGFloat prog = (float)totalBytesWritten/totalBytesExpectedToWrite;
        NSLog(@"downloaded %d%%", (int)(100.0*prog));
    
    }
    
    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {
        // unused in this example
    }
    
    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
        NSData *d = [NSData dataWithContentsOfURL:location];
        UIImage *im = [UIImage imageWithData:d];
        dispatch_async(dispatch_get_main_queue(), ^{
            self.image = im;
    
        });
    }
    
    -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
        NSLog(@"completed; error: %@", error);
    }
    
    0 讨论(0)
提交回复
热议问题