iPhone:处理同一代理中两个请求的两个(或多个)响应

时间:2012-02-11 04:34:14

标签: iphone

我在视图控制器中调用NSURLConnection异步方法调用。我想在同一个代表处理两个请求的两个回应。请告诉我实现这一目标的最佳方法是什么?我正在开发iOS 5 SDK。

更新:

 // Class A
 [serverconns setDelegate:self];
 connection = [serverconns executeAsyncHttpPost :firstjsonrequest];

 [serverconns setDelegate:self];
 connection = [serverconns executeAsyncHttpPost :secondjsonrequest];


- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
}

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

- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    // logs the error
}

- (void) connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSData *responseData = [[NSData alloc] initWithData:appendData];
    //HOW CAN WE HANDLE TWO RESPONSES FOR TWO REQUEST in the same Delegate
    if (responseData) 
    {
          // doing something
    }
}

    //Class B: ServerConnection

- (NSURLConnection *) executeAsyncHttpPost :(id) jsonParams
{
    NSString *urlstr = [NSString stringWithFormat:@"%@", baseURL];
    urlstr = [urlstr stringByAppendingFormat:method];

    NSURL *pUrl = [NSURL URLWithString:urlstr];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:pUrl];
    NSData *requestData = [NSData dataWithBytes:[jsonParams UTF8String] length:[jsonParams length]];

    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-type"];
    [request setHTTPBody: requestData];

    return [[NSURLConnection alloc] initWithRequest:request delegate:delegateResponder startImmediately:YES];

}
    -(void) setDelegate:(id)newDelegate
{
    delegateResponder = newDelegate;
}

5 个答案:

答案 0 :(得分:3)

将你的连接保存在某个地方(也许是代表的ivar)

- (void) connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSData *responseData = [[NSData alloc] initWithData:appendData];
    //HOW CAN WE HANDLE TWO RESPONSES FOR TWO REQUEST in the same Delegate
    if (responseData) 
    {
        if (connection == yourFirstConnection) {
            // doing something for first connection
        } else {
            // doing something for second connection
        }
    }
}

只是指出代码的一些小问题

NSString *urlstr = [NSString stringWithFormat:@"%@", baseURL];
urlstr = [urlstr stringByAppendingFormat:method];

应该替换为

NSString *urlstr = [baseURL absoluteString];
urlstr = [urlstr stringByAppendingString:method];

并将NSURLConnection的两个(或更多或数组)弱/赋值属性添加到您的类A(连接委托)

@property (assign) NSURLConnection *myFirstConnection;
@property (assign) NSURLConnection *mySecondConnection;
// assume only need to handle two connection otherwise NSArray should be used instead

比你的B级(创建连接)

- (NSURLConnection *) executeAsyncHttpPost :(id) jsonParams
{
    NSString *urlstr = [baseURL absoluteString];
    urlstr = [urlstr stringByAppendingString:method];

    NSURL *pUrl = [NSURL URLWithString:urlstr];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:pUrl];
    NSData *requestData = [NSData dataWithBytes:[jsonParams UTF8String] length:[jsonParams length]];

    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-type"];
    [request setHTTPBody: requestData];

    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegateResponder startImmediately:YES];
    delegateResponder.myFirstConnection = connection;
    // delegateResponder.mSecondConnection = connection;
    return connection;

}

答案 1 :(得分:2)

如果我是你,我会创建一个继承NSURLConnection的CustomClass。我将添加名为tag的属性。

当我启动CustomClass时,我会设置tag属性并使用它来确定正在处理哪个请求

CustomURLConnection *connection = [[CustomURLConnection alloc] initWithRequest:request delegate:self tag:1];

- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate   tag:(int)_tag
 {
if(self = [super initWithRequest:request delegate:delegate])
{   
   self.tag = _tag;
}

现在你发布的代码中添加了这个

- (void) connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSData *responseData = [[NSData alloc] initWithData:appendData];
    //HOW CAN WE HANDLE TWO RESPONSES FOR TWO REQUEST in the same Delegate
    if (responseData) 
    {
      if (connection.tag == 1){

      }
    }
}

return self;
  }

答案 2 :(得分:1)

我认为所有提到的解决方案都是“丑陋的”。我不会使用委托方法实现解决方案,而是创建基于块的解决方案。如果你有兴趣,我可以发一个例子。我会使用AFNetworking类来实现这种方法。


以下是一个类的示例,该类在不使用委托实现的情况下处理2个不同的响应,而不是使用AFNetworking库选择块。

- (void)JSONFromService
{
    // create the first request and set the methods that handle the return values (either NSData or NSError in this case) in blocks ... 

    NSURL *firstURL = [NSURL URLWithString:@"http://dl.dropbox.com/u/6487838/test1.html"];
    NSURLRequest *firstRequest = [NSURLRequest requestWithURL:firstURL];
    AFHTTPRequestOperation *firstOperation = [[AFHTTPRequestOperation alloc] initWithRequest:firstRequest];

    [firstOperation setCompletionBlockWithSuccess:^ (AFHTTPRequestOperation *operation, id object) 
    {
        NSString *firstString = [[NSString alloc] initWithData:object encoding:NSASCIIStringEncoding];
        NSLog(@"%@", firstString);
    } failure:^ (AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"%@", error);
    }];
    [firstOperation start];



    // create the second request and set the methods that handle the return values (either NSData or NSError in this case) in blocks ... 

    NSURL *secondURL = [NSURL URLWithString:@"http://dl.dropbox.com/u/6487838/test2.html"];
    NSURLRequest *secondRequest = [NSURLRequest requestWithURL:secondURL];
    AFHTTPRequestOperation *secondOperation = [[AFHTTPRequestOperation alloc] initWithRequest:secondRequest];

    [secondOperation setCompletionBlockWithSuccess:^ (AFHTTPRequestOperation *operation, id object) {
        NSString *secondString = [[NSString alloc] initWithData:object encoding:NSASCIIStringEncoding];
        NSLog(@"%@", secondString);
    } failure:^ (AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"%@", error);
    }];
    [secondOperation start];
}

答案 3 :(得分:0)

我通常将NSURLConnection子类化并添加属性来存储处理响应所需的任何上下文。

由于委托方法传入NSURLConnection,您只需将其强制转换回子类并访问上下文。

看看this example

答案 4 :(得分:0)

我认为您应该将所有连接保留在activeConnections数组中。每次完成后,您都会执行[activeConnections indexForObject:connection],并使用索引相应地更新您的委托方法。

现在,一种更简洁的方法(从我的观点来看,更好的方式,但这取决于你要传输的数据有多大)是使用队列。我将提供一个小例子并为其添加注释:

// we assume you have 2 requests: req1, req2

//now, create a new dispatch queue    
dispatch_queue_t netQueue = dispatch_queue_create("com.mycompany.netqueue",DISPATCH_QUEUE_SERIAL);

//execute the operations in the queue ASYNC
//is very important to dispatch this ASYNC on a background thread, otherwise your UI will be stuck until the request finishes 
dispatch_async(netQueue, 
^{
  // We are on a background thread, so we won't block UI events (or, generally, the main run loop)
  NSHTTPURLResponse *response = nil;
  NSError *error = nil;
  NSData *data = nil;




  //We can call the request synchronous and block this thread until completed
  data = [NSURLConnection sendSynchronousRequest:req1
                               returningResponse:&response 
                                           error:&error];

  dispatch_async(dispatch_get_main_queue(),
  ^{
    //call your delegate with the appropriate method for req1 
    //be sure to copy the contents in data, as we will reuse it with the next request 
  });

  //We can call the other request synchronous and block this thread until completed
  data = [NSURLConnection sendSynchronousRequest:req2
                               returningResponse:&response 
                                           error:&error];
  dispatch_async(dispatch_get_main_queue(),
  ^{
  //call your delegate with the appropriate method for req2 
  });




  //and this can go on forever. If you have many requests to execute, simply put them in a loop


 });
 dispatch_release(netQueue);