2013-02-25 82 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