25

AFURLSessionManager を使用して新しいダウンロード タスクを作成しています。

AFURLSessionManager* manager = ...

NSProgress* p = nil;
NSURLSessionDownloadTask* downloadTask =
        [manager downloadTaskWithRequest:request
                                 progress:&p
                              destination:^NSURL*(NSURL* targetPath, NSURLResponse* response) {...}
                        completionHandler:^(NSURLResponse* response, NSURL* filePath, NSError* error) {...}
        ];
[downloadTask resume];

ファイルは正常にダウンロードされますが、進行状況の通知を受け取るにはどうすればよいですか?

pは常に nil に設定されます。私はそのために問題を提起しました。

また、マネージャーに電話をかけようとしましsetDownloadTaskDidWriteDataBlockたが、そこで進行状況の通知を受け取りますが、ファイルがダウンロードされた後、すべてがグループ化されて表示されます。

この領域は、AFNetworking 2.0 ではまだ少しバグがあるようです。

何か案は?

4

4 に答える 4

45

KVO を使用してオブジェクトのfractionCompletedプロパティを観察する必要があります。NSProgress

NSURL *url = [NSURL URLWithString:@"http://www.hfrmovies.com/TheHobbitDesolationOfSmaug48fps.mp4"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
NSProgress *progress;
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request progress:&progress destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
    // …
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
    [progress removeObserver:self forKeyPath:@"fractionCompleted" context:NULL];
    // …
}];

[downloadTask resume];
[progress addObserver:self
            forKeyPath:@"fractionCompleted"
               options:NSKeyValueObservingOptionNew
               context:NULL];

次に、オブザーバー メソッドを追加します。

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"fractionCompleted"]) {
        NSProgress *progress = (NSProgress *)object;
        NSLog(@"Progress… %f", progress.fractionCompleted);
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

もちろん、keyPathおよび/またはobjectパラメーターをチェックして、それが観察したいオブジェクト/プロパティであるかどうかを判断する必要があります。

setDownloadTaskDidWriteDataBlock:メソッド from AFURLSessionManager(AFHTTPSessionManager継承元) を使用して、ダウンロードの進行状況の更新を受信するためのブロックを設定することもできます。

[session setDownloadTaskDidWriteDataBlock:^(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {
    NSLog(@"Progress… %lld", totalBytesWritten);
}];

この AFNetworking メソッドは、URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:メソッドをNSURLSessionDownloadDelegateプロトコルからより便利なブロック メカニズムにマップします。

ところで、Apple の KVO 実装はひどく壊れています。Mike Ash がMAKVONotificationCenterで提案したような、より優れた実装を使用することをお勧めします。Apple の KVO が壊れている理由に興味がある場合は、Mike Ash によるKey-Value Observing Done Rightをお読みください。

于 2013-10-15T12:07:07.097 に答える
18

私は同様の問題に直面し、解決策を見つけました。

以下のリンクを確認してください: http://cocoadocs.org/docsets/AFNetworking/2.0.1/Categories/UIProgressView+AFNetworking.html

#import <AFNetworking/UIKit+AFNetworking.h>

UIProgressView で利用可能な追加のメソッドを使用します

setProgressWithDownloadProgressOfTask:animated:

私がそれをした方法:

NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request  progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response){
    NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) firstObject]];
    return [documentsDirectoryPath URLByAppendingPathComponent:[targetPath lastPathComponent]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error){
    NSLog(@"File downloaded to: %@", filePath);

}];

[self.progressView setProgressWithDownloadProgressOfTask:downloadTask animated:YES];
[downloadTask resume];
于 2013-10-26T15:28:19.870 に答える
0

Swift のシンプルなソリューション:

let sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
let sessionManager = AFURLSessionManager(sessionConfiguration: sessionConfiguration)
let request = NSURLRequest(URL: url)
let sessionDownloadTask = sessionManager.downloadTaskWithRequest(request, progress: nil, destination: { (url, response) -> NSURL in

            return destinationPath.URLByAppendingPathComponent(fileName) //this is destinationPath for downloaded file

            }, completionHandler: { response, url, error in

                //do sth when it finishes
        })

次の 2 つのオプションがあります。

  1. UIProgressViewと_setProgressWithDownloadProgressOfTask:

    progressView.setProgressWithDownloadProgressOfTask(sessionDownloadTask, animated: true)
    
  2. AFURLSessionManagerと_setDownloadTaskDidWriteDataBlock:

    sessionManager.setDownloadTaskDidWriteDataBlock { session, sessionDownloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
    
        let progress = Float(totalBytesWritten)/Float(totalBytesExpectedToWrite)
            //do sth with current progress
    }
    

最後に次のことを忘れないでください。

sessionDownloadTask.resume()
于 2015-12-09T08:14:47.947 に答える