11

のドキュメントにNSProgressよると、-[NSProgress localizedAdditionalDescription]ダウンロード速度と残り時間を報告できることがわかります。

1.61 GB の 3.22 GB (2 KB/秒) — 残り 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];
}

ダウンロードObserver.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]);
}

これは以下のみを出力します:

0/100

100 バイトのゼロ KB

localizedAdditionalDescriptionダウンロード速度と残り時間を印刷するにはどうすればよいですか?

4

1 に答える 1

17

まず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および他のクラス プロパティに従って、ローカライズされた説明をフォーマットするだけです。ドキュメントの定数セクションを参照してください。これらの値を操作して、ローカライズされた説明の出力を比較できます。

ダウンロードの残り時間を表示したい場合は、 を使用できますNSProgressEstimatedTimeRemainingKey。悪いニュースは、残り時間を手動で計算する必要があることです。参考:ダウンロードの残り時間を(正確に)見積もるには?

NSProgressThroughputKeyデータ処理の速度を 1 秒あたりのバイト数で示すものを設定してみました。残り時間が計算されると思っNSProgressていましたが、そうはなりませんでした。

AFNetworking ソースも参照してください。アップロードおよびダウンロード タスクにAFURLSessionManagerTaskDelegateのインスタンスを使用します。NSProgress

于 2014-02-12T08:03:19.353 に答える