Mic*_*itz 2 timeout objective-c nsurlconnection grand-central-dispatch ios
我正在为iOS应用程序编写网络类.该类将负责所有日志记录和网络流量.我有一个问题,我必须一次发送可能数千个请求,但NSURLConnections超时是因为在所有NSURLConnections启动之前不会调用委托方法,此时超时期限已到期.我正在为Drupal使用rest API,不幸的是,我不知道用一个请求创建多个实例的方法.如何在发送回复的同时收到回复?如果我使用GCD来传递NSURLConnections的创建,那会解决问题吗?我想我必须通过遍历对象的整个操作来发送和发送到GCD以释放主线程来回答响应.
-(BOOL)sendOperation:(NetworkOperation)op
NetworkDataType:(NetworkDataType)dataType
JsonToSend:(NSArray *)json
BackupData:(NSArray *)data
{
if(loggingMode)
{
return YES;
}
NSURLConnection *networkConnection;
NSData *send;
NSString *uuid = [self generateUUID];
NSMutableArray *connections = [[NSMutableArray alloc] init];
NSMutableURLRequest *networkRequest;
for (int i=0; i<[json count] && (data ? i<[data count] : YES); i++)
{
if(op == Login)
{
/*Grab all cookies from the server domain and delete them, this prevents login failure
because user was already logged in. Probably find a better solution like recovering
from the error*/
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:
[[NSURL alloc] initWithString:networkServerAddress]];
for (NSHTTPCookie *cookie in cookies)
{
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
}
networkRequest = [[NSMutableURLRequest alloc] initWithURL:
[NSURL URLWithString:[networkServerAddress stringByAppendingString:@"/user/login"]]];
}
else if(op == StartExperiment)
{
networkRequest = [[NSMutableURLRequest alloc] initWithURL:
[NSURL URLWithString:[networkServerAddress stringByAppendingString:@"/node"]]];
}
else if(op == Event || op == EndExperiment || op == SendAll)
{
networkRequest = [[NSMutableURLRequest alloc] initWithURL:
[NSURL URLWithString:[networkServerAddress stringByAppendingString:@"/node"]]];
}
else if(op == Logout)
{
networkRequest = [[NSMutableURLRequest alloc] initWithURL:
[NSURL URLWithString:[networkServerAddress stringByAppendingString:@"/user/logout"]]];
}
send = [[json objectAtIndex:i] dataUsingEncoding:NSUTF8StringEncoding];
//Set the headers appropriately
[networkRequest setHTTPMethod:@"POST"];
[networkRequest setValue:@"application/json"
forHTTPHeaderField: @"Content-type"];
[networkRequest setValue:[NSString stringWithFormat:@"%d", [send length]]
forHTTPHeaderField:@"Content-length"];
[networkRequest setValue:@"application/json"
forHTTPHeaderField:@"Accept"];
//Set the body to the json encoded string
[networkRequest setHTTPBody:send];
//Starts async request
networkConnection = [[NSURLConnection alloc] initWithRequest:networkRequest delegate:self];
//Successfully created, we are off
if(networkConnection)
{
[networkConnectionsAndData setValue:[[NSMutableArray alloc] initWithObjects:uuid,
[[NSNumber alloc] initWithInt:op], [[NSNumber alloc] initWithInt:dataType], [[NSMutableData alloc] init], (data ? [data objectAtIndex:i] : [NSNull null]), nil]
forKey:[networkConnection description]];
}
else //Failed to conn ect
{
NSLog(@"Failed to create NSURLConnection");
return NO;
}
}
[[self networkOperationAndConnections] setObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:[[NSMutableArray alloc] initWithObjects:connections, nil], @"connections", [[NSMutableArray alloc] init], @"errors", nil]
forKey:uuid];
return YES;
}
Run Code Online (Sandbox Code Playgroud)
字典用于跟踪每个NSURLConnection的相关数据,还可以将NSURLConnections组合成一个组,以确定整个操作的最终成功或失败.
更新
AFNetworking是完成这个项目的关键.它不仅大大清理了代码,还处理了在发送这么多请求时继承的所有线程问题.更不用说AFNetworking我可以将所有请求一起批量处理为单个操作.像AFNetworking一样使用块,比NSURLConnections的标准代表更清洁,更好.
您肯定需要允许NSURLRequest/Connection在另一个线程上运行.(不是主线!)
为了清晰而编辑**:我注意到你对" //Starts async request" 的评论,我想确保你意识到你的电话没有你所期望的典型"异步"功能.它实际上只是同步触发请求,但由于它是一个Web请求,它本身就是异步行为.您希望将这些请求实际放在另一个线程上以获得完整的异步行为.
除此之外,我真的建议在这里深入研究Apple的网络示例项目:MVCNetworking
至于你问题的具体细节,有几种方法可以做到这一点.
initWithRequest:<blah> delegate:<blah> startImmediately:FALSE,然后NSURLConnection使用:scheduleInRunLoop:forMode在另一个线程的运行循环上安排实例:
NSOperation+ 来执行此操作NSOperationQueue.)NSURLConnection来创建/启动连接而不是执行alloc/init:sendAsynchronousRequest:queue:completionHandler:说实话,我上面的快速答案不足以完成这种项目,你需要做一些研究来填补空白,特别是对于NSOperationQueue,这就是MVCNetworking项目将帮助你的地方.
网络连接是一种变幻无常的野兽 - 即使它们只是通过尝试同时执行太多工作而在后台线程上运行,您也可以超时并终止连接!我会认真地重新考虑一次开放几千个NSURLConnections,使用一个NSOperationQueue可以帮助解决这个问题.
其他资源: 这是第三方图书馆,可以让您的网络冒险减少痛苦: