我从iOS开始,我正在尝试使用webview编写一个简单的文件下载器。
我需要下载多个文件,但不能同时调用(就像我见过的例子);它应该像桌面浏览器一样:它应该能够在浏览时随时添加新操作,而不是连续下载...
阅读和阅读后,我发现了afnetworking,我一直在努力实现它并没有取得好成绩......因为我不知道如何管理多个操作!
我的问题是,一旦我添加了许多操作,我该如何单独调用它们?例如,停止或取消其中一个。
这是代码:
...
AFHTTPClient *httpClient;
...
- (void)DownloadFileFromUrl:(NSString *)fileURL{
NSURL *url = [NSURL URLWithString:fileURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//I've tried to init httpClient here each time, or at didLoad with a nil baseurl
httpClient =[[AFHTTPClient alloc]initWithBaseURL: [NSURL URLWithString:@"fileURL"]];
[httpClient.operationQueue setMaxConcurrentOperationCount:10];
AFDownloadRequestOperation *operation = [[AFDownloadRequestOperation alloc] initWithRequest:request
targetPath:targetPath
shouldResume:YES];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
//COOL!
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//failure case
//remove the file if saved a part of it!
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:targetPath error:&error];
if (error) {
//ERROR
}
if ([operation isCancelled]) {
}
}];
[operation setProgressiveDownloadProgressBlock:^(AFDownloadRequestOperation *operation1, NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpected, long long totalBytesReadForFile, long long totalBytesExpectedToReadForFile)
{
if (totalBytesExpectedToReadForFile > 0) {
dispatch_async(dispatch_get_main_queue(), ^{
//NSLog(@"Operation%i: bytesRead: %d", 1, bytesRead);
//NSLog(@"Operation%i: totalBytesRead: %lld", 1, totalBytesRead);
//NSLog(@"Operation%i: totalBytesExpected: %lld", 1, totalBytesExpected);
//NSLog(@"Operation%i: totalBytesReadForFile: %lld", 1, totalBytesReadForFile);
//NSLog(@"Operation%i: totalBytesExpectedToReadForFile: %lld", 1, totalBytesExpectedToReadForFile);
});
}
}];
[httpClient.operationQueue addOperation:operation];
//OR ?[httpClient enqueueHTTPRequestOperation:operation];
}
当我只下载一个文件时,一切似乎都没问题,因为调用了httpClient.operationQueue.operations [0] ...我得到了它的数据,我无法从任何地方做到[[httpClient.operationQueue] .operations [0]]暂停];
但是,如果我尝试从另一个站点下载第二个文件(我有一个webview进行导航),并将其添加到httpClient.operationQueue,它似乎不会将它添加到同一个队列;我的意思是,如果我用计时器打电话:
NSLog(@"Operations %d", httpClient.operationQueue.operations.count);
我没有得到“操作2”,但是:
Operations 1
Operations 1
这很烦人,因为有时当我尝试获取operations.count以便找到我想要的操作并用它做某事时,我找不到它!它是在“并行”队列中的东西!
有没有办法获得并处理所有活动操作?或者每次添加一个存储每个操作的方法? (但能够“使用它们”,不是为了只读目的......比如调用暂停,取消等)
很明显,我错过了一些重要的东西,而且我是编程的初学者,但是真的很感激任何帮助! (并且,如果你能明确,那就更好......我是初学者)
非常感谢,真的。
修改 在做了一些研究并尝试了一些事情之后,我已经解决了将httpclient添加到单例中,并且仅在App初始化时使用随机baseurl进行设置。然后我将每个操作添加到Singleton-httpClient,尽管它的url。它似乎工作,因为现在它存储所有的连接,我可以访问它们现在问题循环它,但我知道这不是好方法;它更容易更清洁,我知道我错过了管理某种阵列中的活动连接的方式,而不是使用一个“棘手的”httpclient与虚假的baseurl进行所有操作(使用不同的URL) 所以...我仍然接受建议和良好做法:)。谢谢!
答案 0 :(得分:3)
好的一些提示在手。 我强烈建议您阅读NSOperationQueue和NSOperation API doc:
NSOperationQueue: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/NSOperationQueue_class/Reference/Reference.html#//apple_ref/doc/uid/TP40004592
我不鼓励你尝试迭代NSOperationQueue的操作数组。为什么?因为它很高,你可能会因竞争条件问题而结束。
然而。我建议你采用以下方法:
1)在你的单例类中创建一个NSDictionary,其中: key:将代表文件名 value:与该请求关联的AFDownloadRequestOperation请求。
2)当您需要下载新文件时: 验证字典中是否存在,如果不创建新操作并将其添加到字典中。
2.1)如果确实存在,您可能需要: 2.1.1)由于AFDownloadRequestOperation从NSOperation延伸,您可以取消它。要在检查此条件之前执行此操作:isExecuting,isFinished。如果这些条件中的任何一个为假,您可以取消该操作并将其从字典中删除。