2013-10-16 1 views
49

私はAFNetworking 2.0でiOS 7用のアプリケーションを書き直しています。リクエストのバッチを一度に送信し、進行状況を追跡するという問題に取り掛かりました。古いAFNetworkingではAFHTTPClientenqueueBatchOfHTTPRequestOperations:progressBlock:completionBlock:メソッドがありましたが、これは明らかにリファクタリングされています。複数のリクエストをエンキューする方法はちょっと混乱しています。AFNetworking 2でリクエストをバッチする方法は?

私はAFHTTPSessionManagerのサブクラスを作成しました。私はPOST:...GET:...メソッドを使用してサーバーと通信しています。しかし、私はコードとドキュメントの中で、以前のAFHTTPClientのように複数のリクエストを同時にエンキューすることはできません。

AFURLConnectionOperationの文書化されていないbatchOfRequestOperations:progressBlock:completionBlock:メソッドが見つかりましたが、これはiOS 6のようです。

新しいNSURLSessionという概念の中で、バッチリクエストや新しいAFNetworking機能の検討に欠かせないものがあります。誰かがここに正しい道で私を助けることを願っています!

tl; dr:AFHTTPSessionManagerサブクラスで一括してリクエストを送信するにはどうすればよいですか? 2.0をAFNetworkingで

+0

AFHTTPSessionManagerは、4つの重要なデリゲートを実装するAFURLSessionManagerを実装します。 NSURLSessionDelegate、NSURLSessionTaskDelegate、NSURLSessionDataDelegate、NSURLSessionDownloadDelegateです。 NSURLSessionDataDelegateは、GET/POSTに最も一般的に使用されます。私たちはsessionManagerをシングルトンしているので、これらのメソッドをオーバーライドするだけです。完了ハンドラのコールバックの1つが - (void)URLSession:(NSURLSession *)セッション dataTask:(NSURLSessionDataTask *)dataTask ... completionHandler :(void(^)(NSURLSessionResponseDisposition disposition))completionHandler。 –

答えて

84

ありがとうございますSendmoreには、GitHub issue where Mattt explainsへのリンクがあります。この機能はもう機能しません。新しいNSURLSession構造ではこれが不可能な明確な理由があります。タスクは操作ではないため、依存関係や操作のバッチを使用する古い方法は機能しません。

// Create a dispatch group 
dispatch_group_t group = dispatch_group_create(); 

for (int i = 0; i < 10; i++) { 
    // Enter the group for each request we create 
    dispatch_group_enter(group); 

    // Fire the request 
    [self GET:@"endpoint.json" 
     parameters:nil 
      success:^(NSURLSessionDataTask *task, id responseObject) { 
        // Leave the group as soon as the request succeeded 
        dispatch_group_leave(group); 
      } 
     failure:^(NSURLSessionDataTask *task, NSError *error) { 
        // Leave the group as soon as the request failed 
        dispatch_group_leave(group); 
       }]; 
} 

// Here we wait for all the requests to finish 
dispatch_group_notify(group, dispatch_get_main_queue(), ^{ 
    // Do whatever you need to do when all requests are finished 
}); 

私はこの簡単になります何かを書く見たい:

は私がNSURLSessionを使用してバッチリクエストすることが可能となりdispatch_groupを使用してこのソリューションを作成しました、ここでは(擬似)コードでありますもしこれがAFNetworkingにマージできるものなら(うまく実装されていれば)、マットと話し合い、議論してください。私の意見では、このようなことを図書館自体で行うのは素晴らしいことです。しかし、私はそれにいくらか余裕がある時をチェックする必要があります。

+0

2回目の反復が入る前に最初の反復がグループから離れる場合はどうなりますか? – Chrizzor

+0

これは問題ではありません。その場合、forループはまだスレッドをブロックしています。したがって、forループが完了した後でのみ、 'dispatch_group_notify()'が呼び出され、すべての "反復"がブロックを呼び出すグループから離れると、グループに他のすべての要求が追加されます。 –

+0

もちろん、この非同期のものはすべて私が盲目になります:)ありがとう! – Chrizzor

1

AFHTTPClientAFHTTPRequestOperationManagerAFHTTPSessionManagerに分割されているので、おそらくあなたはoperationQueue性質を有している、最初に始めることができます。

1

現在、NSURLSessionタスクは、同じ種類のパターン要求操作では使用できません。この問題に関してMattt Thompson hereからの回答を参照してください。

直接の回答:依存関係やバッチが必要な場合は依然として依頼操作を使用する必要があります。

3

ちょうどスレッドを更新...私は同じ問題を抱えていたし、いくつかの研究の後、私はいくつかの良い解決策を見つけたが、私はこの1つに固執することを決めた:

私はBoltsと呼ばれるプロジェクトを使用しています。 @ Mac_Cain13によって投稿を超えるので、同じサンプルのために、それは次のようになります。基本的に、それは、すべてのタスクを積み重ね待ってアンラップこれ以上のタスクがなくなるまで、すべてが最後の完了を完了した後だ

[[BFTask taskWithResult:nil] continueWithBlock:^id(BFTask *task) { 
    BFTask *task = [BFTask taskWithResult:nil]; 
    for (int i = 0; i < 10; i++) { 
     task = [task continueWithBlock:^id(BFTask *task) { 
      return [self executeEndPointAsync]; 
     }]; 
    } 
    return task; 
}] continueWithBlock:^id(BFTask *task) { 
    // Everything was executed. 
    return nil; 
}];; 

- (BFTask *) executeEndPointAsync { 
    BFTaskCompletionSource *task = [BFTaskCompletionSource taskCompletionSource]; 
    [self GET:@"endpoint.json" parameters:nil 
     success:^(NSURLSessionDataTask *task, id responseObject) { 
     [task setResult:responseObject]; 
     } 
     failure:^(NSURLSessionDataTask *task, NSError *error) { 
     [task setError:error]; 
     }]; 
    }]; 
    return task.task; 
} 

ブロックが実行されます。

同じことをするもう1つのプロジェクトはRXPromiseですが、私の場合はBoltsのコードが明らかです。

postまたは getすることができ requestについては
3

、あなたに、まずあなたがこのような操作を作成する必要があり、バッチ操作のためのAFNetworking 2.0を使用することができます。

//Request 1 
NSString *strURL = [NSString stringWithFormat:@"your url here"]; 
NSLog(@"scheduleurl : %@",strURL); 
NSDictionary *dictParameters = your parameters here 
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:strURL parameters:dictParameters error: nil]; 

AFHTTPRequestOperation *operationOne = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 
operationOne = [AFHTTPResponseSerializer serializer]; 

[operationOne setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) 
{ 
    //do something on completion 
} 
failure:^(AFHTTPRequestOperation *operation, NSError *error) 
{ 
    NSLog(@"%@",[error description]); 
}]; 

//Request 2 
NSString *strURL1 = [NSString stringWithFormat:@"your url here"]; 
NSLog(@"scheduleurl : %@",strURL); 
NSDictionary *dictParameters1 = your parameters here 
NSMutableURLRequest *request1 = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:strURL1 parameters:dictParameters1 error: nil]; 

AFHTTPRequestOperation *operationTwo = [[AFHTTPRequestOperation alloc] initWithRequest:request1]; 
operationTwo = [AFHTTPResponseSerializer serializer]; 

[operationTwo setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) 
{ 
    //do something on completion 
} 
failure:^(AFHTTPRequestOperation *operation, NSError *error) 
{ 
    NSLog(@"%@",[error description]); 
}]; 

//Request more here if any 

を次のようにバッチ操作を実行します。

//Batch operation 
//Add all operation here 
NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:@[operationOne,operationTwo] progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) 
{ 
    NSLog(@"%i of %i complete",numberOfFinishedOperations,totalNumberOfOperations); 
    //set progress here 
    yourProgressView.progress = (float)numberOfFinishedOperations/(float)totalNumberOfOperations; 

} completionBlock:^(NSArray *operations) 
{ 
    NSLog(@"All operations in batch complete"); 
}]; 

[[NSOperationQueue mainQueue] addOperations:operations waitUntilFinished:NO];