2013-02-25 81 views
8

我知道这个问题被问了很多次的SO,但我没让它在我的项目工作...iOS版 - 异步NSURLConnection的内部的NSOperation

所以,我想继承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 

我在做什么错?

+0

我想'NSURLConnection'必须从主线程调用,它不会做任何东西,如果从后台线程调用...即使它是从主线程调用,它仍然实际上在后台做网络的东西,然后再次从主线程调用你的委托函数... – jjv360 2013-02-25 14:27:06

+0

对,所以如何我让我的NSOperation在主线程上执行呢? – Oleg 2013-02-25 14:38:58

+0

尝试'[[NSOperationQueue mainQueue] addOperation:operation]'... – jjv360 2013-02-25 14:40:23

回答

8

您需要正确地配置您的操作执行的“并发操作”

Concurrency Programming Guide: Configuring Operations for Concurrent Execution

您需要返回isConcurrent = YES,妥善处理对方状态标志,在韩国国际志愿者组织兼容方式isExecutingisFinished


要说明的总体思路这里是从工程师脉冲后,描述他们的一些简单的解决方案遵循的演示代码,你可以下载和审查。

Pulse Engineering Blog: Concurrent Downloads using NSOperationQueues **

此代码还处理该NSURLConnection的是确保它启动时,它在主线程上线开始活跃runloop的要求。

(**链接现在是archive.org,我觉得脉冲被收购,并已采取了旧网站关闭)

+0

谢谢你的链接,它帮助! – Oleg 2013-02-26 09:03:31

+0

感谢您的回答:-) – Arkan 2013-09-17 15:04:25

+0

链接中断。 :( – Suz 2015-01-30 18:35:13