【问题标题】:Easier way to send JSON Data with Objective-C to PHP server?使用 Objective-C 将 JSON 数据发送到 PHP 服务器的更简单方法?
【发布时间】:2014-04-30 01:28:32
【问题描述】:

我有一个 PHP RESTful 服务器,我连接到它以根据我的 Objective-c 程序调用的 URL 路径调用方法。我使用ASIHTTPRequestSBJson

一切正常,但我在不同的控制器中执行请求,现在所有这些控制器中都有重复的方法。在单个类中抽象该代码(请求)的最佳方法是什么,以便我可以轻松地重用代码,从而使控制器更简单。

请把我从我认为是冗余和重复的编码序列中解救出来。

我尝试过制作一个单例类,但是每个视图控制器需要不同的请求连接点,并且大多数视图控制器需要在调用成功的方法时调用特定的操作,我不知道如何处理这一切。

这是我的代码模板目前在 Objective-c 程序中的样子:

//*1) Somewhere at the top of my .m file I have this*

//These are the suffixes to the URL path that I connect to at my server, 
//depending on the action required 
NSString *const RequestCreateCustomer = @"Create/Customer";
NSString *const RequestUpdateCustomer = @"Update/Customer";
NSString *const RequestDeleteCustomer = @"Delete/Customer";

//*2) Then I have my connection invocation code*

//Method invocation, all of them look something like this
-navigationButton{
...
    [self retrieveWithRequestStringType:RequestUpdateCustomer];
}

-(void)retrieveWithRequestStringType:(NSString*)typeOfRequest{

    NSLog(@"Retrieve %@ method called", typeOfRequest);
    NSString *urlString = [NSString stringWithFormat:@"%@/Secure/CB/%@", @"http://www.defaultStapleURLToMyServer.com/CB", typeOfRequest];
    NSString *encodedUrlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL *url = [[NSURL alloc] initWithString:encodedUrlString];

    serverRequest = nil;
    serverRequest = [ASIFormDataRequest requestWithURL:url];
    [serverRequest addRequestHeader:@"Content-Type" value:@"application/json"];
    [serverRequest addRequestHeader:@"Request-Method" value:@"POST"];

    //Normally at this point depending on the request type, I prepare some data that needs to be sent along with the request

    NSMutableDictionary *completeDataArray = [[NSMutableDictionary alloc] init];    
    if([typeOfRequest isEqualToString:RequestCreateCustomer]){
        [serverRequest setUserInfo:[NSDictionary dictionaryWithObject:RequestCreateCustomer forKey:@"RequestType"]];
        if( ! [self validateAndPrepareAllData:&completeDataArray]){
            return;
        }

    }
    else if([typeOfRequest isEqualToString:RequestUpdateCustomer]){
        [serverRequest setUserInfo:[NSDictionary dictionaryWithObject:RequestUpdateCustomer forKey:@"RequestType"]];
        if( ! [self validateAndPrepareAllData:&completeDataArray]){
            return;
        }
    }
    else if([typeOfRequest isEqualToString:RequestDeleteCustomer]){
        [serverRequest setUserInfo:[NSDictionary dictionaryWithObject:RequestDeleteCustomer forKey:@"RequestType"]];
        if( ! [self validateAndPrepareCustomerIdData:&completeDataArray]){
            return;
        }

    }

    NSString *jsonString = [completeDataArray JSONRepresentation];
    [serverRequest appendPostData:[jsonString dataUsingEncoding:NSUTF8StringEncoding]];

    [serverRequest setDelegate:self];
    [serverRequest setDidFinishSelector:@selector(requestSucceeded:)];
    [serverRequest setDidFailSelector:@selector(requestFailed:)];
    [serverRequest startAsynchronous];
}


//*3) And heres the connection did succeed, and connection did fail methods*

-(void)requestSucceeded:(ASIHTTPRequest*)request{

    NSInteger statusCode = [[[request responseHeaders] objectForKey:@"StatusCode"] intValue];
    NSLog(@"StatusCode: %@", [[request responseHeaders] objectForKey:@"StatusCode"]);

    NSString *myString = [[NSString alloc] initWithData:[request responseData] encoding:NSUTF8StringEncoding];


    NSDictionary *JSONDictionary = [myString JSONValue];

    switch (statusCode) {
        case 400:
        case 401:
        {
            NSLog(@"display error message");
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:[[request.responseString JSONValue] objectForKey:@"Message"] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil];
            [alert show];
            break;
        }
        case 200:
            NSLog(@"status code = 200 so successful");

            //Created customer request succeeded
            if([[[request userInfo] objectForKey:@"RequestType"] isEqualToString:RequestCreateCustomer]){
                [self.delegate addedCustomerVCWithCustomer:[[CustomerDataModel alloc] initWithJSONData:[JSONDictionary objectForKey:@"CustomerObject"]]];
                [self cancelModalView];

            } 
            //Edit customer request succeeded
            else if([[[request userInfo] objectForKey:@"RequestType"] isEqualToString:RequestUpdateCustomer]){
                [self.delegate editedCustomerVCWithCustomer:[[CustomerDataModel alloc] initWithJSONData:[JSONDictionary objectForKey:@"CustomerObject"]]];
                [self cancelModalView];
            }
            //Delete customer request succeeded
            else if([[[request userInfo] objectForKey:@"RequestType"] isEqualToString:RequestDeleteCustomer]){
                [self.delegate deletedCustomer:customer];
                [self cancelModalView];
            }
            break;
        default:
            [SVProgressHUD showErrorWithStatus:[NSString stringWithFormat:@"went to none: %d or %@", (int)statusCode, [[request responseHeaders] objectForKey:@"StatusCode"]]];
            NSLog(@"went to none: %d or %@", (int)statusCode, [[request responseHeaders] objectForKey:@"StatusCode"]);
            break;
    }
    [SVProgressHUD dismiss];
}



-(void)requestFailed:(ASIHTTPRequest*)request{

    if([[[request userInfo] objectForKey:@"RquestType"] isEqualToString:RequestCreateCustomer]){
        NSLog(@"retrieving states failed so trying again");
        [self addCustomerRequest];
    }
    else if(){
       //... you get the point
    }
}

有人可以提供替代解决方案吗?

【问题讨论】:

  • 我尝试了一个简单的方法。看看我的问题stackoverflow.com/questions/19706004/…
  • 嘿,谢谢,伙计,你使用的块很好,但它仍然意味着跨多个视图控制器的重复,我真的不想要这种规模。

标签: ios objective-c json asihttprequest


【解决方案1】:

创建一个包含块/委托(但更喜欢块)的新类.. 假设 Request.h 和 Request.m.. 并使用块参数创建一个公共方法.. 示例

这应该是公共方法

typedef void(^CompletionBlock)(id results);
typedef void(^ErrorBlock)(NSError *error);

- (void)setCompetionBlock:(CompletionBlock)block;

- (void)setErrorBlock:(ErrorBlock)error;

并创建一个变量名.. 这应该是私有变量

CompletionBlock completionBlock;
ErrorBlock errorBlock;

并在您的 .m 中声明此方法

- (void)setCompletionBlock:(CompletionBlock)aCompletionBlock {
    completionBlock = [aCompletionBlock copy];
}

- (void)setErrorBlock:(ErrorBlock)aError {
    errorBlock = [aError copy];
}

- (void)reportSuccess:(id)results {
    if (completionBlock) {

        dispatch_async(dispatch_get_main_queue(), ^{
            completionBlock(results);
        });
    }
}

- (void)reportFailure:(NSError *)error {
    if (errorBlock) {

        dispatch_async(dispatch_get_main_queue(), ^{
            errorBlock(error);
        });
    }
}

并在您的成功方法下调用[self reportSuccess:jsonSuccess];,在您的代码中它是-(void)requestSucceeded:(ASIHTTPRequest*)request{[self reportFailure:NSerror*]-(void)requestFailed:(ASIHTTPRequest*)request

并调用这个类

Request *req = [Request alloc]init];
[req retrieveWithRequestStringType:@"sample"];
[req setCompletion:^(id result){

}];
[req setErrorBlock:(NSError *error) {

}];

【讨论】:

  • 谢谢发帖,代码好像到处都是,能整理一下吗?看起来很混乱。我试图了解什么去哪里。我不想要的是重复,但我也想要一种简单的方法来处理不同视图控制器之间的成功和失败请求,根据视图控制器的不同,它们的行为会有所不同,有些会禁用字段,有些会显示警报等。
  • 我试图理解你的帖子,但 atm 看起来我仍然需要在不同的视图控制器之间复制和粘贴 blocks 的代码块,我正试图避免这种情况胡安。
  • 如果您查看代码伙伴,您会发现它不是共享实例,而是为每种类型的请求连接点创建块到服务器。我试图保持代码干净,以便我可以拥有一个共享实例,一个将集中和管理我所有连接的单例。如果您有解决方案,请告诉我,因为我找不到可以立即使用的解决方案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-16
  • 1970-01-01
  • 2011-02-02
  • 1970-01-01
  • 2015-02-15
  • 1970-01-01
相关资源
最近更新 更多