iOSアプリのネットワーククラスを作成しています。このクラスはすべてのロギングとネットワークトラフィックを処理します。一度に何千ものリクエストを送信しなければならない問題がありますが、すべてのNSURLConnectionsが開始されるまでデリゲートメソッドが呼び出されないため、NSURLConnectionsはタイムアウトしています。私はDrupal用のAPIを使用しています。残念ながら、1つのリクエストで複数のインスタンスを作成する方法はわかりません。同時にどのように回答を受け取ることができますか? GCDを使用してNSURLConnectionsの作成を渡すと、問題が解決するのでしょうか?私は、返事に答えるためにメインのスレッドを解放するために、GCDに送信して送信するオブジェクト全体を反復する操作全体を渡す必要があると思います。多くのリクエストを送信するときにNSURLConnectionのタイムアウトが発生するのはなぜですか?
-(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;
}
辞書は各NSURLConnectionとの相関データを追跡するために使用され、また、グループに一緒に1つのグループにNSURLConnectionsは、全体の動作の最終的な成功または失敗を決定します。
更新
AFNetworkingは、このプロジェクトを終えにおける鍵となりました。実質的にコードをクリーンアップするだけでなく、すべてのスレッドの問題を処理して、非常に多くのリクエストを送信します。 AFNetworkingではもちろん、すべてのリクエストをまとめて1つの操作にまとめることもできます。 AFNetworkingのようなブロックの使用は、NSURLConnectionsの標準代理人よりはるかにクリーンで優れたソリューションでした。
私はそれが初期化という印象の下にありました、そこでは非同期要求が開始されています。 sendAsynchronousRequestを使用しない限り、非同期リクエストではありませんか?迅速なご回答をありがとうございました。 –
申し訳ありませんが、私はそこにはっきりしていませんでした。 「 '//非同期リクエストを開始します」というあなたのコメントに気づき、典型的な「非同期」機能から期待していたものがあなたの呼び出しではないことに気づいたかったのです。本当にリクエストを同期して実行しているだけですが、Webリクエストからは本質的に非同期的に動作します。完全な非同期動作のために、これらの要求を実際に別のスレッドに配置する必要があります。 – MechEthan
サードパーティのライブラリへのリンクを追加しました。あなたに役立つことがありますので、こちらをお勧めします。 – MechEthan