Grand Central Dispatch的互联网请求的良好模式?

时间:2011-07-06 04:03:11

标签: objective-c cocoa asihttprequest grand-central-dispatch

我目前正在使用带有GCD队列的同步ASIHTTPRequest从Internet下载数据,然后使用JSONKit解析响应数据。您如何看待这种模式?提前谢谢。

这是我的代码:

    dispatch_async(queue, ^(void) {

        // Request is ASIHTTPRequest.
        [request startSynchronous];

        // Parse JSON.
        NSArray *array = [[request responseData] objectFromJSONDataWithParseOptions:JKParseOptionLooseUnicode];

        // Callback on the main queue to update UI.
        dispatch_async(dispatch_get_main_queue(), ^(void) {
            callbackBlock(array);
        });
    });

编辑:我使用ASIHTTPRequest的原因是我需要修改OAuth的请求标头并使用POST方法上传图像。

4 个答案:

答案 0 :(得分:12)

所以你替换了这个

- (void)doDownload {
    NSURL *url = [NSURL URLWithString:@"http://foobar.com"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    connection = [[NSURLConnection alloc] initWithRequest:aURLRequest delegate:self];
    receivedData = [[NSMutableData data] retain];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [_receivedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSArray *array = [_receivedData objectFromJSONDataWithParseOptions:JKParseOptionLooseUnicode];
    callbackBlock(array);       
}

用这个 -

- (void)doDownload {
    NSURL *url = [NSURL URLWithString:@"http://foobar.com"];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(queue, ^(void) {
        [request startSynchronous];
        NSArray *array = [[request responseData] objectFromJSONDataWithParseOptions:JKParseOptionLooseUnicode];

        // Callback on the main queue to update UI.
        dispatch_async(dispatch_get_main_queue(), ^(void) {
            callbackBlock(array);
        });
    });
}

来自ASIHTTPRequest的10,000多行代码

它带给你什么?

NSURLConnection是完全异步的,使用GCD,缓存,自动压缩/解压缩等等。

出于这个原因,并且完全依赖于您提供的(可能不完整的)信息,我会说这是一段非常糟糕的代码。

当然,上下文就是一切 - 你可能有一个非常非常非常好的理由重新实现Apple提供的已有的Library代码功能。

答案 1 :(得分:2)

在WWDC2010,对于网络编程,Apple建议使用RunLoop进行异步编程。

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

NSURLConnection异步请求是最有效的方法之一。但是如果你想使用ASIHTTPRequest,它怎么样? (ASIHTTPRequest异步请求是使用NSOperationQueue实现的,它与NSURLConnection异步不同。)

ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setCompletionBlock:^{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
        NSData *responseData = [request responseData];
        /* Parse JSON, ... */
        dispatch_async(dispatch_get_main_queue(), ^{
            callbackBlock(array);
        });
    });
}];
[request setFailedBlock:^{
    NSError *error = [request error];
    /* error handling */
}];
[request startAsynchronous];

答案 2 :(得分:0)

对于单个网络连接,该代码看起来没问题,但如果您使用ASIHTTPRequest,则可能是移动应用程序。对于多个并发下载,我将实现一个队列(请参阅ASIHTTPRequest文档中的“使用队列”),您可以在其中指定最大同时连接数(例如,在GPRS上使用2和在wifi上使用8)或限制带宽。然后,在完成选择器中使用GDC或其他东西来运行主UI线程中的数据处理。

实质上,对于简单的情况,使用带有ASIHTTPRequest的块只会为您提供与NSURLConnection不同的语法,如fakeAccount22所述。 NSURLConnection也有同步方法,因此您可以避免外部依赖(以及潜在的错误/问题来源)并在块中使用它。

答案 3 :(得分:0)

最好的方法是在获取回调时使用gcd,而不是在启动请求时使用。然后你可以在后台线程解析并通知主线程。祝你好运!