我知道这个问题在 SO 上被问过很多次,但我没有设法让它在我的项目中工作......
所以,我想子类化 NSOperation
并让它使用 NSURLConnection
下载文件。正确的做法是什么?
这是我的代码不起作用:
首先,我将所有操作添加到一个循环中:
DownloadFileOperation *operation;
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
for (int i=0; i<10; i++) {
operation = [[DownloadFileOperation alloc] init];
operation.urlString = pdfUrlString;
[queue addOperation:operation];
operation = nil; }
这是我的子类:
@interface DownloadHandbookOperation : NSOperation <NSURLConnectionDelegate>
{
}
@property (strong, nonatomic) NSString *urlString;
@end
@implementation DownloadHandbookOperation
{
NSString *filePath;
NSFileHandle *file;
NSURLConnection * connection;
}
- (void)start
{
if (![NSThread isMainThread])
{
[self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO];
return;
}
NSURL *url = [[NSURL alloc] initWithString:[self.urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
[req addValue:@"Basic ***=" forHTTPHeaderField:@"Authorization"];
connection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
}
- (void)connection:(NSURLConnection *)conn didReceiveResponse:(NSURLResponse *)response
{
NSString *filename = [[conn.originalRequest.URL absoluteString] lastPathComponent];
filename = [filename stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:filename];
[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
file = [NSFileHandle fileHandleForUpdatingAtPath:filePath] ;
if (file)
{
[file seekToEndOfFile];
}
else
[self finish];
}
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
{
if (file) {
[file seekToEndOfFile];
}
[file writeData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
[file closeFile];
[self finish];
}
- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
{
connection = nil;
[self finish];
}
- (void)cancel
{
[super cancel];
[connection cancel];
}
- (void)finish
{
NSLog(@"operationfinished.");
}
@end
我做错了什么?
最佳答案
您需要正确配置操作以作为“并发操作”执行
Concurrency Programming Guide: Configuring Operations for Concurrent Execution
您需要返回isConcurrent = YES
并妥善管理其他州旗帜,isExecuting
和 isFinished
以符合 KVO 的方式。
为了说明这里的总体思路,Pulse 的工程师发表了一篇文章,其中描述了他们的解决方案以及一些易于理解的演示代码,您可以下载和查看。
Pulse Engineering Blog: Concurrent Downloads using NSOperationQueues **
此代码还处理了 NSURLConnection 在具有事件运行循环的线程上启动的要求,方法是确保它在主线程上启动。
(** 链接现在指向 archive.org,我认为 pulse 已被收购并已关闭其旧站点)
关于iOS - NSOperation 中的异步 NSURLConnection,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15066532/