1

次のメソッドは、AFNetworking を使用してリクエストを Web サービスに送信し、(成功すると) レスポンスに基づいて動作します。AFNetworking はリクエストを非同期的に行い、ブロックを使用して成功または失敗を判定します。したがって、リクエストを送信するメソッドは次のようになります (簡略化)。

- (void)sendRequestForConnector:(NSString *)connector 
          success:(void (^)(NSData *responseXml))success
          failure:(void (^)(NSError *error))failure
{
  AFHTTPRequestOperation *operation = [self HTTPRequestOperationForConnector:connector];
  [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) 
  {
    [self handleSuccessForConnector:connector response:[operation responseData]];
    success([operation responseData]);
  } 
  failure:^(AFHTTPRequestOperation *operation, NSError *error) 
  {
    [self handleFailureForConnector:connector error:error];
    failure(error);
  }

  [operation start];
}

別のクラスでは、このメソッドを使用して Web サービスを複数回呼び出します。前の呼び出しが成功すると、次の呼び出しが行われます。このメソッドは次のようになります (簡潔にするために失敗ブロックは省略されています)。

- (void)import 
{
   [client sendRequestForConnector:@"cities" success:^{
     [client sendRequestForConnector:@"categories" success:^{
       [client sendRequestForConnector:@"categoryTranslations" success:^{
         [client sendRequestForConnector:@"products" success:^{
           [client sendRequestForConnector:@"productTranslations" success:^{

             [self finishImport];

           }];
         }];
       }]; 
     }];
   }];
}

これは機能しますが、ご覧のとおり、各 Web サービス呼び出しは別のネストされた成功ブロック ハンドラーを追加します。これを行うにはもっと良い方法があるに違いないと私には思えますが、思いつきません。

できれば、次の呼び出しを行う前に前の呼び出しが完了するのを待ち、GCD のようなものを使用して import メソッド全体を非同期的に呼び出したいと考えています。ただし、AFNetworking は同期呼び出しを行うようには設計されていません。

これを達成する方法についてのアイデアは大歓迎です。または、私の現在のソリューションは進むべき道ですか?

4

5 に答える 5

3

私は応答を待つ必要があり、最後のアップロードが完了した後にアップロードのために ws を呼び出す必要があるのと同じ状況にありました。

これを行うにはいくつかの方法があります

1)dispatch_group全部終わったときに使用して通知することができます。

2) セマフォを作成して ws を 1 つずつ呼び出す

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(queue, ^{
    dispatch_semaphore_t test = dispatch_semaphore_create(0);
    for (NSUInteger i = 0; i < self.uploadDocument.count; ++i) {
       // My custom method with block which call ws 
      [self uploadMultipleImagesUsingAFNetworkingMultipartFormatWithDocumentId:[[self.uploadDocument objectAtIndex:i] valueForKey:kDocument_DocumentId] andIndex:i withCompletionBlock:^(id responseObj, NSError *error) {

            // Your Logic 

            dispatch_semaphore_signal(test);
        }];
        dispatch_semaphore_wait(test, DISPATCH_TIME_FOREVER);

    // Here comes when your all ws finish 
      dispatch_async(dispatch_get_main_queue(), ^{
              [self.tblUpload reloadData];
              [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

        });
    }
于 2016-07-01T04:43:52.050 に答える
0

私は同じ問題に直面しており、PromiseKitAFNetworking-PromiseKitの導入をしばらく考えていました。しかし、私は最終的にあきらめて、シンプルでやや面倒な解決策を考え出しました。

そこで、kvo の主な目的である「step」というプロパティを導入しました。次に、非同期呼び出しごとに、終了時にそのステップをマークする必要があります。次に、kvo メソッドはプロセス全体を次のステップに移動します。つまり、kvo メソッドはフロー制御を行います。

たとえば、sendRequestForConnector:@"cities" はステップ 1、@"categories" はステップ 2、@"categoryTranslations" はステップ 3、@"products" はステップ 4 になります。各成功ブロックの最後に、独自の価値に足を踏み入れます。したがって、kvo はこのステップが終了したことを認識し、次の非同期メソッドを呼び出す必要があります。

kvo メソッドは、プロセス全体を監視および制御します。

switch (step.intValue) {
    case 1: //call step2; break;
    case 2: //call step3; break;
    case 3: //call step4; break;
    case 4: //call step5; break;
    ...
    case x: // finish, remove kvo on step
}

これまでのところ、それは私の目的を果たし、私のコードはずっときれいに見えます。

于 2016-07-01T04:34:10.997 に答える
-2

同期呼び出しを行う場合は、NSStringの「stringWithContentsOfURL:」メソッドを使用するだけです。したがって、ループ内のこのコードを使用して、NSURLのNSArrayをループするだけです。

NSError* error = nil;
NSString* htmlSource = [NSString stringWithContentsOfURL:theNSURL encoding:NSUTF8StringEncoding error:&error];
if (error) {
    // handle error
}
// parse htmlSource
于 2012-11-21T11:26:14.697 に答える