我在视图控制器中调用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;
}
答案 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);