2012-04-24 18 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