2012-04-24 21 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"); 
    } 
} 

我不太清楚如何構建這個考慮到我的網絡方法的異步性質。在兩次之前的可用性檢查收到他們的回覆之前,通常會達到最後一個條件。

可用性檢查方法看起來是這樣的:

- (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:validateEmailWithSuccess:failure繼續調用validateUsernameWithSuccess:failure等。

我只是想強調上面例子中進程的狀態機性質。

+0

這正是我正在尋找的那種設置。的確,我確實需要閱讀塊。謝謝。 – 2012-04-25 13:54:36