多个异步Web服务请求NSURLConnection iOS

时间:2011-05-13 12:45:01

标签: iphone objective-c network-programming nsurlconnection nsurlrequest

我有一个问题,我不知道如何解决。在传递单个请求时,我可以毫无问题地向REST服务发出请求。

我现在的问题是基于该响应,我得到一些值,包括ID。然后,检索到的所有ID都需要另外请求收集新信息。

我的猜测是在数组或字典中加载所有特定请求并从中创建请求。有人对此有一些有用的提示吗?然后,检索到的信息将填充UITableView。

3 个答案:

答案 0 :(得分:4)

我建议您在此问题上使用同步 - 异步模式。

您需要实现两个同步方法:

// Fetch the array of ID's
-(NSArray*)fetchItemIDsWithError:(NSError**)error;

// Fetch the item for a ID
-(Item*)fetchItemForID:(NSString*)itemID error:(NSError**)error;

使用同步代码实现这些是容易和可测试的。您可以轻松使用dataWithURL…stringWithContentsOfURL…sendSynchronousRequest…或ASIHTTPrequest等简单方法,并为此编写直接的单元测试。与并发代码通常结束的方式相比,代码也将非常易于维护和扩展。

现在到第二步,创建一个异步包装器,我会使用一个委托和一个这样的方法签名:

@protocol FetchItemsDelegate <NSObject>
-(void)didFetchItems:(NSArray*)array;
-(void)failedFetchItemsWithError:(NSError*)error;
@end

-(void)fetchItemsWithAsyncDelegate:(id<FetchItemsDelegate>)delegate;

您已经拥有了所需的所有代码,因此您所要做的就是阻止异步部分。这段代码将很好地分离和直接。 Probaly不超过这个:

-(void)fetchItemsWithAsyncDelegate:(id<FetchItemsDelegate>)delegate;
{
    [self performSelectorInBackground:@selector(backgroundFetchItemsWithDelegate:)
                           withObject:delegate];      
}

-(void)backgroundFetchItemsWithDelegate:(id<FetchItemsDelegate>)delegate;
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    BOOL success = YES;
    NSMutableArray* items = [NSMutableArray array];
    NSError* error = nil;
    NSArray* itemIDs = [self fetchItemIDsWithError:&error];
    if (itemIDs) {
        for (NSString* itemID in itemIDs) {
           Item* item = [self fetchItemForID:itemID
                                       error:&error];
           if (item) {
               [items addObject:item];
           } else {
               success = NO;
               break;
           }
        }
    } else {
        success = NO;
    }
    if (success) {
        [delegate performSelectorOnMainThread:@selector(didFetchItems:)
                                   withObject:[NSArray arraiWithArray:items]
                                waitUntilDone:NO];
    } else {
        [delegate performSelectorOnMainThread:@selector(failedFetchItemsWithError)
                                   withObject:error
                                waitUntilDone:NO];
    }
    [pool release];
}

我在这里写了一篇关于这个主题的更长篇博文:http://blog.jayway.com/2011/04/28/sync-asyn-pair-pattern-easy-concurrency-on-ios/

答案 1 :(得分:0)

你的问题有点模糊,但我想我可能会理解你的问题。我通常在执行http请求时使用协议实现委托模式:

@protocol HttpDelegate
   -(void) httpDidFinish;
   -(void) httpError:(NSError *) error;
@end

并在HttpClient类中:

-(void) connectionDidFinishLoading:(NSURLConnection *)connection {
    [self.delegate httpDidFinish];
}

您的控制器(或其他类)实现HttpDelegate,并在httpDidFinish中生成第二个请求或填充您的表。在这种情况下,由于这是一个两步过程,而不是在控制器中实现HttpDelegate,我可能会添加另一个类,TwoStepProcessor和TwoStepProcessorDelegate。 TwoStepProcessorDelegate就像HttpDelegate,除了它有:

-(void) secondStepFinished:

您的控制器实现。

答案 2 :(得分:0)

它的解决方案取决于你现有的实现。(我在这里只考虑两种情况。)

案例I If you are having a different class for managing connection related task, a separate class that has NSURLConnection Delegate methods.(Asynchronous..)

  • 您需要运行for循环来请求所有20个ID请求,并为其注册通知,并将ID作为通知名称。当连接完成加载后,它会向您的观察类发布通知,此处使用通知名称,您可以更新相应ID的相关时间表。 [这里你需要创建该连接处理程序类的不同对象] ...在这里你需要等待计划加载你可以做什么你可以将活动指示器放在单元的附加视图中,直到加载计划。(你可以在这种情况下显示名称)

案例II If its singleton or in the same class which you are using.(we can not create it's multiple objects)..(it will have the performance cost.) one by one request.

  • 您需要逐个发送请求并更新单元格的内容,直到完成为止。这意味着您发送了ID 1的请求,当它的响应响起时,您可以更新单元格并发送下一个请求。等等。

如果您向我们发送处理连接活动的方式,将会很有帮助。

谢谢,