2012-04-24 10 views
0

私は最近、ASIHttpRequestライブラリからAFNetworkingに切り替えました。私はシンプルさが気に入っていますが、私の非同期コードをどのように構造化するのかを理解するのにはまだ苦労しています。コントローラの非同期ネットワークコードの構成

この登録シナリオを検討してください。

  • まず、入力したメールアドレスが利用可能かどうかを確認します。
  • 次へ入力したユーザー名が利用可能かどうかを確認します。
  • 上記の両方が有効で利用可能な場合は、本物のサインアップリクエストを送信します。

私のコードは次のようになります。

- (void)signUp{ 

    BOOL hasValidEmail = [self validateEmail:email]; 
    BOOL hasValidUsername = [self validateUsername:username]; 

    if(!hasValidEmail){ 
     NSLog(@"Invalid email"); 
     return; 
    } 

    if(!hasValidUsername){ 
     NSLog(@"Invalid username"); 
     return; 
    } 

    if (hasValidEmail && hasValidUsername) { 
     NSLog(@"Go ahead and create account"); 
    } 
} 

私はネットワーキング方法の非同期性を考慮して、どのように構造化するのかよく分かりません。以前の2つの可用性チェックが応答を受け取る前に、最後の条件に達することがよくあります。

方法を確認する可用性は次のようになります。

- (BOOL)validateEmail:(NSString*)email{ 

    __block NSString* emailAlreadyExists = @""; 

    NSString* url = [NSString stringWithFormat:@"user/emailexists/%@", email]; 

    [[APIClient sharedClient] getPath:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 

     emailAlreadyExists = [responseObject valueForKey:@"exists"]; 

    } failure:^(AFHTTPRequestOperation *operation, NSError* error) { 
     NSLog(@"Email availability check failed: %@", error.localizedDescription); 
    }]; 

    if([emailAlreadyExists isEqualToString:@"true"]){ 
     return NO; 
    } 

    return YES; 
} 

多分それは改善し必要ちょうど私のブロックのスキルですが、私は本当にあなたがこのようなシナリオを構築する方法を聞きたいのですが?

コードサンプルが "いい"とはいえ、私は実際にあなたが知っているパターンや優れた技術を探しています。

ありがとうございました。

答えて

0

私は通常、これらのことをステップに分割し、前のステップが成功したときに次のステップを開始します。ブロックはこの目的のために通過するのが大変です。

明らかにこの文句を言わないコンパイル、うまくいけば、それはあなたがこれを行う方法のいくつかのアイデアを与えることができます。

typedef enum 
{ 
    SignupErrorNetworkError, 
    SignupErrorEmailAlreadyTaken, 
    SignupErrorUsernameAlreadyTaken, 
} SignupError; 

typedef enum 
{ 
    // These steps must be performed in this order. 
    SignupStepValidateEmail, 
    SignupStepValidateUsername, 
    SignupStepCreateAccount, 
} SignupStep; 

typedef void (^SignupSuccessBlock)(); 
typedef void (^SignupFailureBlock)(SignupError reason); 

// Call this to sign up. 
- (void)signupWithSuccess:(SignupSuccessBlock)success failure:(SignupFailureBlock)failure 
{ 
    // Start the first step of the process. 
    [self performSignupStep:SignupStepValidateEmail success:success failure:failure]; 
} 

// Internal method. Don't call this from outside. 
- (void)performSignupStep:(SignupStep)step success:(SignupSuccessBlock)success failure:(SignupFailureBlock)failure 
{ 
    switch (step) 
    { 
     case SignupStepValidateEmail: 
      [[APIClient sharedClient] getPath:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
       if ([responseObject valueForKey:@"exists"]) 
       { 
        if (failure) failure(SignupErrorEmailAlreadyTaken); 
        return;    } 
       } 
       // Start next async step in signup process. 
       [self performSignupStep:SignupStepValidateUsername success:success failure:failure]; 
      } failure:^(AFHTTPRequestOperation *operation, NSError* error) { 
       if (failure) failure(SignupErrorNetworkError); 
      }]; 
      break; 
     case SignupStepValidateUsername: 
      // Similar to the step above. Starts the create account step on success. 
      break;    
     case SignupStepCreateAccount: 
      // Similar to the step above. Call the success block when done. 
      break;    
    } 
} 

スイッチが長すぎると醜いなっている場合は、また別の方法に手順を作成し、削除することができstep-enum:validateUsernameWithSuccess:failureなどを呼び出して続行するvalidateEmailWithSuccess:failure

上記の例では、プロセスのステートマシンの性質を強調したかっただけです。

+0

これはまさに私が探していた種類のセットアップでした。確かに私はブロックを読み上げる必要があります。ありがとうございました。 –

関連する問題