几个反应:
您正在启动 a NSURLConnection
connectionWithRequest
(触发NSURLConnectionDataDelegate
方法),但您显然忽略了这一点并启动了dataWithContentsOfURL
. 你应该选择一个或另一个,但不要两者都做。
我建议您采用NSOperation
基于 - 的解决方案,因为您肯定希望 (a) 享受并发;但是(b)将并发操作限制在某个合理的数量(比如 4 或 5),否则您将有请求超时并失败。
在获取文件名方面,您可以使用lastPathComponent
从NSURL
. (我的下载操作,在下面使用,如果你不提供明确的文件名,实际上会自动使用它。)
您还没有说明如何确定来自远程服务器的文件名列表,因此我们必须看看您如何知道要检索哪些图像。
如果这是出于您自己的目的,那很好,但我听说苹果拒绝通过蜂窝连接请求过多数据的应用程序(并且 2000 张图像肯定符合条件)。坦率地说,即使 Apple 没有大惊小怪,你也应该在使用他们的大量数据计划之前询问用户。您可以使用Reachability来确定用户是通过 wifi 还是通过蜂窝网络连接,如果是后者,您可能需要发出警告。
但我建议一些看起来像的东西(假设你有一些NSArray
版本NSString
的 URL ......显然调整这个为你的 URL 列表的任何形式):
NSOperationQueue *downloadQueue = [[NSOperationQueue alloc] init];
downloadQueue.maxConcurrentOperationCount = 4;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
for (NSString *urlString in urlStrings)
{
NSURL *url = [NSURL URLWithString:urlString];
NSString *path = [docsPath stringByAppendingPathComponent:[url lastPathComponent]];
if (![fileManager fileExistsAtPath:path]) {
DownloadOperation *downloadOperation = [[DownloadOperation alloc] initWithURL:url];
downloadOperation.downloadCompletionBlock = ^(DownloadOperation *operation, BOOL success, NSError *error) {
if (error) NSLog(@"download of %@ failed: %@", operation.url, error);
};
[downloadQueue addOperation:downloadOperation];
}
}
而那个下载操作可能是这样的。显然,使用NSOperation
您想要的任何基于下载器,但我建议您使用一种不会将整个下载加载到内存中的下载器,而是直接将其流式传输到持久存储的下载器。
如果您不想花哨,则可以执行以下操作:
NSOperationQueue *downloadQueue = [[NSOperationQueue alloc] init];
downloadQueue.maxConcurrentOperationCount = 4;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
for (NSString *urlString in urlStrings)
{
NSURL *url = [NSURL URLWithString:urlString];
NSString *path = [docsPath stringByAppendingPathComponent:[url lastPathComponent]];
if (![fileManager fileExistsAtPath:path]) {
[downloadQueue addOperationWithBlock:^{
NSString *path = [docsPath stringByAppendingPathComponent:[url lastPathComponent]];
NSData *data = [NSData dataWithContentsOfURL:url];
if (data)
[data writeToFile:path atomically:YES];
}];
}
}
显然,使用您想要下载的任何下载操作类,但希望您了解基本概念。创建一个NSOperation
-based 下载,然后为每个需要下载的文件提交一个。