iOS - NSOperation内部的异步NSURLConnection [英] iOS - Async NSURLConnection inside NSOperation

查看:125
本文介绍了iOS - NSOperation内部的异步NSURLConnection的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题在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(强,非原子)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委托: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

我错了?

解决方案

您需要正确配置操作以作为并发操作执行



并发编程指南:配置并发执行操作



您需要返回 isConcurrent = YES 并正确管理其他状态标志, isExecuting isFinished KVO兼容的方式。






为了说明这里的一般想法是Pulse的工程师的一篇文章,容易跟踪演示代码,你可以下载和审查。

Pulse工程博客:使用NSOperationQueues并发下载 **



此代码还处理NSURLConnection在



(**链接现在到archive.org,我想脉搏已被获取并且已经采取了他们的旧网站)


I know this question was asked many times on SO, but I didn't manage to make it work in my project...

So, I want to subclass NSOperation and make it download a file using NSURLConnection. What is the right way to do it? here is my code which doesn't work: First, I'm adding all my operations in a loop:

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; }

And here is my subclass:

@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

What am I doing wrong?

解决方案

You need to properly configure your operation to execute as a "concurrent operation"

Concurrency Programming Guide: Configuring Operations for Concurrent Execution

You need to return isConcurrent = YES and properly manage the other state flags, isExecuting and isFinished in a KVO compliant manner.


To illustrate the general idea here is a post from the engineers at Pulse that describes their solution with some easy to follow demo code you can download and review.

Pulse Engineering Blog: Concurrent Downloads using NSOperationQueues **

This code also handles the requirement that NSURLConnection is started on a thread with an active runloop by ensuring that it starts it on the main thread.

(** link is now to archive.org, I think pulse was acquired and have taken their old site down)

这篇关于iOS - NSOperation内部的异步NSURLConnection的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆