NSURLConnection和盛大的中央调度

Jon*_*son 35 iphone nsurlconnection grand-central-dispatch

是否可以将NSUrlConnection包装在gcd样式块中并在low_priority队列上运行?

我需要确保我的连接不在主线程上发生,并且连接需要是异步的.我还需要几个同时发出的请求.

如果我去gcd路由,我不确定调用NSUrlConnectionDelegate方法的哪个线程.

NSURLConnection依赖于委托,所以一旦连接完成,处理它的任何包装类都需要调用它的调用者.我不确定如何处理连接工作启动/完成时调用的所有各种回调:

- (void)connection:(NSURLConnection *)aConnection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)incrementalData;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
Run Code Online (Sandbox Code Playgroud)

我应该只调用同步版本但是包含在gcd块中吗?如果我想取消通话,请使用'dispatch_suspend'?

dispatch_async(queue,^{
      NSString* result = [self mySynchronousHttp:someURLToInvoke];
      });

// If I need to cancel
dispatch_suspend(queue);
Run Code Online (Sandbox Code Playgroud)

Kaz*_*oto 53

我建议您在iPhone OS中查看有关网络应用程序的WWDC会话.

  • WWDC 2010 Session 207 - 适用于iPhone OS的网络应用程序,第1部分
  • WWDC 2010 Session 208 - 适用于iPhone OS的网络应用,第2部分

讲师说

"线程是邪恶的"

用于网络编程,建议使用RunLoop进行异步网络编程.使用后台线程(Grand Central Dispatch Concurrent Queue)进行线程安全数据处理,而不是网络编程.

顺便说一下,Blocks和Grand Central Dispatch会议也值得一看.

  • WWDC 2010 Session 206 - 在iPhone上引入块和Grand Central Dispatch
  • WWDC 2010 Session 211 - 通过Grand Central Dispatch简化iPhone应用程序开发

我为异步NSURLConnection编写了一个包装类.


AsyncURLConnection.h

#import <Foundation/Foundation.h>

typedef void (^completeBlock_t)(NSData *data);
typedef void (^errorBlock_t)(NSError *error);

@interface AsyncURLConnection : NSObject
{
    NSMutableData *data_;
    completeBlock_t completeBlock_;
    errorBlock_t errorBlock_;
}

+ (id)request:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock;
- (id)initWithRequest:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock;
@end
Run Code Online (Sandbox Code Playgroud)

AsyncURLConnection.m

#import "AsyncURLConnection.h"

@implementation AsyncURLConnection

+ (id)request:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock
{
    return [[[self alloc] initWithRequest:requestUrl
        completeBlock:completeBlock errorBlock:errorBlock] autorelease];
}

- (id)initWithRequest:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock
{

    if ((self=[super init])) {
        data_ = [[NSMutableData alloc] init];

        completeBlock_ = [completeBlock copy];
        errorBlock_ = [errorBlock copy];

        NSURL *url = [NSURL URLWithString:requestUrl];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [NSURLConnection connectionWithRequest:request delegate:self];
    }

    return self;
}

- (void)dealloc
{
    [data_ release];

    [completeBlock_ release];
    [errorBlock_ release];
    [super dealloc];
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    [data_ setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [data_ appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    completeBlock_(data_);
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    errorBlock_(error);
}

@end
Run Code Online (Sandbox Code Playgroud)

如何使用AsyncURLConnection类.

/*
 * AsyncURLConnection -request:completeBlock:errorBlock: have to be called
 * from Main Thread because it is required to use asynchronous API with RunLoop.
 */

[AsyncURLConnection request:url completeBlock:^(NSData *data) {

    /* success! */

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        /* process downloaded data in Concurrent Queue */

        dispatch_async(dispatch_get_main_queue(), ^{

            /* update UI on Main Thread */

        });
    });

} errorBlock:^(NSError *error) {

    /* error! */

}];
Run Code Online (Sandbox Code Playgroud)

  • 讲师确实说线程是邪恶的,但他并没有说GCD是邪恶的,他说这是未来.在演讲时他说不使用GCD,因为它还不在网络的基础框架中,但现在它是:`[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]` (34认同)
  • 这整个答案现在似乎已经过时了 - 请参阅@ keegan3d的评论 (14认同)