2014-02-04 5 views
7

Согласно documentation for NSProgress я вижу, что -[NSProgress localizedAdditionalDescription] может сообщить скорость загрузки и оставшееся время, например:Использование NSProgress найти скорость загрузки и время, оставшееся

1,61 GB 3,22 ГБ (2 Кб/с) - 2 минуты оставшиеся

Однако, я не в состоянии получить те детали, когда я связать NSProgress к NSURLSessionDownloadTask. Вот мой код:

Downloader.h

@interface Downloader : NSObject 
@property NSProgress *overallProgress; 
-(void)startDownload; 
@end 

Downloader.m

- (void)startDownload { 

    self.overallProgress = [NSProgress progressWithTotalUnitCount:100]; 

    [self.overallProgress setKind:NSProgressKindFile]; 
    [self.overallProgress setUserInfoObject:NSProgressFileOperationKindKey forKey:NSProgressFileOperationKindDownloading]; 


    [self.overallProgress becomeCurrentWithPendingUnitCount:100]; 
    [self work1]; 
    [self.overallProgress resignCurrent]; 
} 

- (void)work1 { 

    NSProgress *firstTaskProgress = [NSProgress progressWithTotalUnitCount:1]; 
    [firstTaskProgress setKind:NSProgressKindFile]; 
    [firstTaskProgress setUserInfoObject:NSProgressFileOperationKindKey forKey:NSProgressFileOperationKindDownloading]; 

    NSURL *downloadURL = [NSURL URLWithString:@"http://ipv4.download.thinkbroadband.com/200MB.zip"]; 
    NSURL *destinationDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject]; 
    NSURL *destinationURL = [destinationDirectory URLByAppendingPathComponent:[downloadURL lastPathComponent]]; 

    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; 
    NSURLSessionDownloadTask *fileDownloadTask = 
    [session downloadTaskWithURL:downloadURL 
       completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error){ 

        [[NSFileManager defaultManager] removeItemAtURL:destinationURL error:NULL]; 

        [[NSFileManager defaultManager] moveItemAtURL:location toURL:destinationURL error:nil]; 

        [firstTaskProgress setCompletedUnitCount:1]; 
       }]; 

    [fileDownloadTask resume]; 
} 

DownloadObserver.m

-(void)viewDidAppear:(BOOL)animated{ 
    [super viewDidAppear:animated]; 

    downloader = [Downloader new]; 

    [downloader addObserver:self 
       forKeyPath:@"overallProgress.fractionCompleted" 
        options:NSKeyValueObservingOptionNew 
        context:NULL]; 

    [downloader startDownload]; 

} 

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    NSLog(@"%@", [downloader.overallProgress localizedAdditionalDescription]); 
} 

Это только печатает:

Нулевой KB 100 байт

Как я могу получить localizedAdditionalDescription печатать скорость и время загрузки остальные?

+0

Марк решил аналогичный вопрос. http://stackoverflow.com/questions/370641/calculating-connection-download-speed – sangony

+0

Нет, мой вопрос заключается в том, как заставить 'NSProgress' выполнять эти вычисления для вас. – Eric

+0

OK ... как насчет этого http://stackoverflow.com/questions/19666883/update-uiprogressview-from-nsprogress – sangony

ответ

14

Прежде всего, totalUnitCount должен соответствовать размеру файла в байтах. Во время процесса загрузки мы меняем completedUnitCount, который отражается на localizedAdditionalDescription. NSProgressKindFile - это подсказка для форматирования этих значений в виде размера файла.

Чтобы правильно установить прогресс, нам нужно использовать методы NSURLSessionDownloadDelegate вместо обработчика блоков. В - URLSession: downloadTask: didWriteData: totalBytesWritten: totalBytesExpectedToWrite: у нас есть вся информация для запуска (totalBytesExpectedToWrite) и обновления (totalBytesWritten).

static void *myContext = &myContext; 

- (void)download { 
    NSURL *downloadURL = [NSURL URLWithString:@"http://ipv4.download.thinkbroadband.com/10MB.zip"]; 
    NSURLSession *session = 
    [NSURLSession 
    sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] 
    delegate:self 
    delegateQueue:[NSOperationQueue mainQueue]]; 

    [[session downloadTaskWithURL:downloadURL] resume]; 
} 

#pragma mark - url session download delegate 

- (void)URLSession:(NSURLSession *)session 
     downloadTask:(NSURLSessionDownloadTask *)downloadTask 
     didWriteData:(int64_t)bytesWritten 
totalBytesWritten:(int64_t)totalBytesWritten 
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite 
{ 
    if (!_progress) { 
     _progress = [NSProgress progressWithTotalUnitCount:totalBytesExpectedToWrite]; 
     _progress.kind = NSProgressKindFile; 
     [_progress addObserver:self forKeyPath:@"fractionCompleted" options:0 context:myContext]; 
    } 

    _progress.completedUnitCount = totalBytesWritten; 
    //[_overallProgress setUserInfoObject:@1024 forKey:NSProgressEstimatedTimeRemainingKey]; 
} 

- (void)URLSession:(NSURLSession *)session 
     downloadTask:(NSURLSessionDownloadTask *)downloadTask 
didFinishDownloadingToURL:(NSURL *)location 
{ 
    [_progress removeObserver:self forKeyPath:@"fractionCompleted"]; 
    _progress = nil; 
    NSLog(@"finished: %@", location); 
} 

-(void)observeValueForKeyPath:(NSString *)keyPath 
        ofObject:(id)object 
         change:(NSDictionary *)change 
         context:(void *)context 
{ 
    if (context == myContext) { 
     self.label.text = [_progress localizedAdditionalDescription]; 
    } 
    else { 
     [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 
    } 
} 

В самом деле, NSProgress не делать каких-либо расчетов. Он просто форматирует локализованное описание в соответствии с userInfo и другими свойствами класса. См. Раздел Constants в документации. Вы можете играть с этими значениями и сравнивать результаты локализованного описания.

Если вы хотите отобразить оставшееся время скачивания, вы можете использовать NSProgressEstimatedTimeRemainingKey. Плохая новость заключается в том, что вам нужно вычислить оставшееся время вручную. Артикул: How to estimate download time remaining (accurately)?

Я попытался установить NSProgressThroughputKey, что указывает скорость обработки данных в байтах в секунду. Я ожидал, что NSProgress рассчитает оставшееся время, но этого не произошло.

См. Также AFNetworking sources: AFURLSessionManagerTaskDelegate использует экземпляры NSProgress для задач загрузки и скачивания.

+0

Спасибо. Поэтому вы должны сами сделать эти расчеты *! До сих пор «NSProgress» - это просто прославленный инкапсулятор для данных прогресса ... Я думаю, что «NSProgress» полезен, когда вы объединяете несколько из них вместе ...? – Eric

+0

Да, это известная особенность – vokilam

+0

Ничего себе, +100 репутации за то, что не отвечали на вопрос ... – Mojo66