2

我在设置与sendAsynchronousRequest:queue:completionHandler:方法(NSURLConnection类)相关的正确配置时遇到了一些困难。

我的情况如下:

我建立了一个管理不同NSURLConnections 的单例类。这个单例实例有一个NSOperation Queue(称为downloadQueue),它向 Web 服务器发出请求并检索字符串路径 (1)。完成后,该路径用于在 Web 服务器 (2) 中下载文件。最后,当文件正确下载后,我需要更新 UI (3)。

我只找到了第一个请求:我可以通过它下载路径。您能建议我执行其他两个步骤的方法吗?

这里有几个问题:

  • 下载队列(downloadQueue)不是主要的,是否可以在该队列中打开一个新的 NSURLConnection ?换句话说,它正确吗?(参见代码片段中的注释)

  • 如果上一个问题是正确的,我该如何获取主队列并更新 UI?

这是我用来执行第一步的代码片段,其中downloadQueue是可以通过访问器方法(@property/ @synthesized)获取的实例变量;

// initializing the queue...
downloadQueue = [[NSOperation alloc] init];    

// other code here...
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[self downloadQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

    if([data length] > 0 && error == nil) {

        // here the path (1)
        // how to perform a second connection?
        // what type of queue do I have to use?              
    }
}];
4

2 回答 2

5

您在执行第一次下载时处于正确的轨道上。

在第一次下载后的完成处理程序块中,您正在计算第二次下载所需的 URL,对吗?然后您可以以相同的方式执行第二次下载:+[NSURLConnection sendAsynchronousRequest:...]使用新的 URL 和相同的队列再次调用。您可以在第一次下载的完成块中执行此操作。

要在第二次下载完成后更新 UI,请切换到该下载完成块内的主队列。您可以使用dispatch_async()or来执行此操作dispatch_sync()(在这种情况下,这无关紧要,因为您在下载队列上没有进一步的工作要做) and dispatch_get_main_queue(),或使用-[NSOperationQueue addOperationWithBlock:]and +[NSOperationQueue mainQueue]

您的代码应如下所示:

// init download queue
downloadQueue = [[NSOperationQueue alloc] init];    

// (1) first download to determine URL for second
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[self downloadQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    if([data length] > 0 && error == nil) {
        // set newURLRequest to something you get from the data, then...
        // (2) second download
        [NSURLConnection sendAsynchronousRequest:newURLRequest queue:[self downloadQueue] completionHandler:^(NSURLResponse *newResponse, NSData *newData, NSError *newError) {
            if([newData length] > 0 && newError == nil) {
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    // (3) update UI
                }];
            }
        }];
    }
}];
于 2012-04-17T21:43:11.063 回答
1

据我所知,要更新 ui,您必须在主线程上执行此操作。ui 可以从其他线程更新,但这些更新并不完全可靠。在我放在一起向 Web 服务发出请求的应用程序中,我使用 dispatch_async() 来访问主队列,然后我从该调用更新表视图,在我的例子中是表视图。

dispatch_async(dispatch_get_main_queue(), ^{
    //block to be run on the main thread
    [self.tableView reloadData];
});

我希望这有帮助。

于 2012-04-17T20:21:52.037 回答