如何下载JSON数据并在iOS中的后台线程中处理它?

时间:2012-10-06 19:47:22

标签: ios multithreading grand-central-dispatch

我需要下载JSON并在iOS5的后台处理它,所以我不冻结我的主线程。我没有取得任何成功。

这是我正在做的事情:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{

    NSURL *url = [NSURL URLWithString:myURL];
    myData = [NSData dataWithContentsOfURL:url];

    [self performSelectorOnMainThread:@selector(processTheData:)
                           withObject:myData
                        waitUntilDone:YES];
}); 

-(void)processTheData:(NSData *)data
{
    //Parse JSON here
}

在上面的代码中,一旦下载完成,我将在Main thrd处理它。当我知道我得到数据时,如何在后台运行它呢?

1 个答案:

答案 0 :(得分:7)

典型的模式是:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{

    NSURL *url = [NSURL URLWithString:myURL];
    myData = [NSData dataWithContentsOfURL:url];

    dispatch_async(dispatch_get_main_queue(), ^{
        [self processTheData:myData];
    });
}); 

或者,假设processTheData本身没有进行UI更新,但是在完成后你想要这样做,典型的方法是在你需要之前不要调度回主队列更新用户界面:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{

    NSURL *url = [NSURL URLWithString:myURL];
    myData = [NSData dataWithContentsOfURL:url];

    [self processTheData:myData];

    dispatch_async(dispatch_get_main_queue(), ^{
        // code that updates UI goes here
    });
}); 

最后,如果您正在对上述代码进行少量调用,那很好,但是如果您可能会做很多请求,那么您应该知道许多服务器会限制它们的并发请求数量将从给定的客户接受。即使服务器没有,您真的想要限制您对服务器的并发请求数量。如果您使用NSOperationQueue而不是GCD,则可以轻松完成此操作。

因此,如果您正在执行多个异步请求,则可能需要执行以下操作(使用第二个示例作为模型)。首先,在开始发起请求之前,您应该创建一个NSOperationQueue对象:

@property (nonatomic, strong) NSOperationQueue *queue;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.queue = [[NSOperationQueue alloc] init];
    self.queue.maxConcurrentOperationCount = 4;
}

然后,您的代码必须执行单独的异步请求:

[self.queue addOperationWithBlock:^{

    NSURL *url = [NSURL URLWithString:myURL];
    myData = [NSData dataWithContentsOfURL:url];

    [self processTheData:myData];

    [[NSOperationQueue mainQueue] addOperationWithBlock:{
        // code that updates UI goes here
    }];
}];