2012-04-02 5 views
3

Ich habe einen Code in ASIHTTP, aber ich möchte auf AFNetworking weitergehen. ich ASIFormDataRequest für einige POST-Anfragen verwendet und dieser Code funktioniert:ASIFormDataRequest in AFNetworking?

NSURL *url = [NSURL URLWithString:@"http://someapiurl"]; 
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url]; 
[request setPostValue:@"123" forKey:@"phone_number"]; 
[request startSynchronous]; 
NSError *error = [request error]; 
if (!error) { 
    NSLog(@"Response: %@", [[request responseString] objectFromJSONString]); 

} 

aber, als ich versuchte, das gleiche mit AFNetworking zu tun, ich in Problem mit Content-Type bekam (ich glaube).

Dieser Code wird AFNetworking, und es funktioniert nicht:

NSURL *url = [NSURL URLWithString:@"http://dev.url"]; 
    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url]; 

    NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys: 
          @"123", @"phone_number", 
          nil]; 
    NSMutableURLRequest *request = [httpClient requestWithMethod:@"POST" path:@"/api/get_archive" parameters:params]; 
    [request setValue:@"application/x-www-form-urlencoded; charset=UTF8" forHTTPHeaderField:@"Content-Type"]; 

    AFHTTPRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest 
*request, NSHTTPURLResponse *response, id JSON) { 
       NSLog(@"Response: %@", JSON); 
      } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){ 
       NSLog(@"Error: %@", error); 
      }]; 
      [operation start]; 

URL in Ordnung ist, wird diese geprüft. Ich bin vom Server immer dieses:

{NSErrorFailingURLKey=http://dev.thisapiurl, NSLocalizedDescription=Expected content type {(
    "text/json", 
    "application/json", 
    "text/javascript" 
)}, got text/html} 

Antwort

4

Das Problem, das Sie haben, ist, weil Sie ein Instanziieren AFJSONRequestOperation, die standardmäßig einen JSON-freundlichen Antworttyp erwartet. Erwarten Sie eine JSON-Antwort? Wenn nicht, sollten Sie eine weniger spezifische Request-Klasse verwenden. Zum Beispiel könnten Sie HTTPRequestOperationWithRequest:.

NSURL *url = [NSURL URLWithString:@"http://dev.url"]; 
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url]; 

NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys: 
         @"123", @"phone_number", 
         nil]; 
NSMutableURLRequest *request = [httpClient requestWithMethod:@"POST" path:@"/api/get_archive" parameters:params]; 
[request setValue:@"application/x-www-form-urlencoded; charset=UTF8" forHTTPHeaderField:@"Content-Type"]; 

//Notice the different method here! 
AFHTTPRequestOperation *operation = [httpClient HTTPRequestOperationWithRequest:request 
    success:^(AFHTTPRequestOperation *operation, id responseObject) { 
      NSLog(@"Response: %@", responseObject); 
     } 
    failure:^(AFHTTPRequestOperation *operation, NSError *error){ 
      NSLog(@"Error: %@", error); 
     }]; 
//Enqueue it instead of just starting it. 
[httpClient enqueueHTTPRequestOperation:operation]; 

Wenn Sie spezifischere Request/Response-Typen (JSON, XML, etc.) haben, können Sie diese spezifischen AFHTTPRequestOperation Subklassen verwenden. Ansonsten benutze einfach den Vanilla HTTP one.

+0

Yap, das ist was ich brauchte. Vielen Dank! – dormitkon

+0

Was meinen Sie mit "erwartet einen JSON-freundlichen Antworttyp"? Meine Webdienste geben die JSON-Antwort zurück. Kannst du dir [diese Frage] anschauen (http://stackoverflow.com/questions/14393131/afjsonrequestoperation-returns-null-response-in-ios) – iOSAppDev

+0

@jagill Was meinst du mit "erwartet einen JSON-freundlichen Antworttyp "? Sucht es nach Content-Type = application/json? – iOSAppDev

1

ich durch die gleiche Sache wie Sie in letzter Zeit ging. Hier ist eine benutzerdefinierte Klasse, die ich geschrieben habe, um so ziemlich jede Netzwerkanfrage zu bearbeiten.

NetworkClient.h:

// 
// NetworkClient.h 
// 
// Created by LJ Wilson on 3/8/12. 
// Copyright (c) 2012 LJ Wilson. All rights reserved. 
// 

#import <Foundation/Foundation.h> 

extern NSString * const ACHAPIKey; 

@interface NetworkClient : NSObject 

+(void)processURLRequestWithURL:(NSString *)url 
         andParams:(NSDictionary *)params 
          block:(void (^)(id obj))block; 

+(void)processURLRequestWithURL:(NSString *)url 
         andParams:(NSDictionary *)params 
        syncRequest:(BOOL)syncRequest 
          block:(void (^)(id obj))block; 

+(void)processURLRequestWithURL:(NSString *)url 
         andParams:(NSDictionary *)params 
        syncRequest:(BOOL)syncRequest 
      alertUserOnFailure:(BOOL)alertUserOnFailure 
          block:(void (^)(id obj))block; 

+(void)handleNetworkErrorWithError:(NSError *)error; 

+(void)handleNoAccessWithReason:(NSString *)reason; 
@end 

NetworkClient.m:

// 
// NetworkClient.m 
// 
// Created by LJ Wilson on 3/8/12. 
// Copyright (c) 2012 LJ Wilson. All rights reserved. 
// 

#import "NetworkClient.h" 
#import "AFHTTPClient.h" 
#import "AFHTTPRequestOperation.h" 
#import "SBJson.h" 

NSString * const APIKey = @"APIKeyIfYouSoDesire"; 

@implementation NetworkClient 

+(void)processURLRequestWithURL:(NSString *)url 
         andParams:(NSDictionary *)params 
          block:(void (^)(id obj))block { 

    [self processURLRequestWithURL:url andParams:params syncRequest:NO alertUserOnFailure:NO block:^(id obj) { 
     block(obj); 
    }]; 
} 

+(void)processURLRequestWithURL:(NSString *)url 
         andParams:(NSDictionary *)params 
        syncRequest:(BOOL)syncRequest 
          block:(void (^)(id obj))block { 
    if (syncRequest) { 
     [self processURLRequestWithURL:url andParams:params syncRequest:YES alertUserOnFailure:NO block:^(id obj) { 
      block(obj); 
     }]; 
    } else { 
     [self processURLRequestWithURL:url andParams:params syncRequest:NO alertUserOnFailure:NO block:^(id obj) { 
      block(obj); 
     }]; 
    } 
} 


+(void)processURLRequestWithURL:(NSString *)url 
         andParams:(NSDictionary *)params 
        syncRequest:(BOOL)syncRequest 
      alertUserOnFailure:(BOOL)alertUserOnFailure 
          block:(void (^)(id obj))block { 

    // Default url goes here, pass in a nil to use it 
    if (url == nil) { 
     url = @"MyDefaultURLGoesHere"; 
    } 

    NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithDictionary:params]; 
    [dict setValue:APIKey forKey:@"APIKey"]; 

    NSDictionary *newParams = [[NSDictionary alloc] initWithDictionary:dict]; 

    NSURL *requestURL; 
    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:requestURL]; 

    NSMutableURLRequest *theRequest = [httpClient requestWithMethod:@"POST" path:url parameters:newParams]; 

    __block NSString *responseString = [NSString stringWithString:@""]; 

    AFHTTPRequestOperation *_operation = [[AFHTTPRequestOperation alloc] initWithRequest:theRequest]; 
    __weak AFHTTPRequestOperation *operation = _operation; 

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 
     responseString = [operation responseString]; 

     id retObj = [responseString JSONValue]; 

     // Check for invalid response (No Access) 
     if ([retObj isKindOfClass:[NSDictionary class]]) { 
      if ([[(NSDictionary *)retObj valueForKey:@"Message"] isEqualToString:@"No Access"]) { 
       block(nil); 
       [self handleNoAccessWithReason:[(NSDictionary *)retObj valueForKey:@"Reason"]]; 
      } 
     } else if ([retObj isKindOfClass:[NSArray class]]) { 
      NSDictionary *dict = [(NSArray *)retObj objectAtIndex:0]; 
      if ([[dict valueForKey:@"Message"] isEqualToString:@"No Access"]) { 
       block(nil); 
       [self handleNoAccessWithReason:[(NSDictionary *)retObj valueForKey:@"Reason"]]; 
      } 
     } 
     block(retObj); 
    } 
             failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
              NSLog(@"Failed with error = %@", [NSString stringWithFormat:@"[Error]:%@",error]); 
              block(nil); 
              if (alertUserOnFailure) { 
               [self handleNetworkErrorWithError:operation.error]; 
              } 

             }]; 

    [operation start]; 

    if (syncRequest) { 
     // Only fires if Syncronous was passed in as YES. Default is NO 
     [operation waitUntilFinished]; 
    } 


} 


+(void)handleNetworkErrorWithError:(NSError *)error { 
    NSString *errorString = [NSString stringWithFormat:@"[Error]:%@",error]; 

    // Standard UIAlert Syntax 
    UIAlertView *myAlert = [[UIAlertView alloc] 
          initWithTitle:@"Connection Error" 
          message:errorString 
          delegate:nil 
          cancelButtonTitle:@"OK" 
          otherButtonTitles:nil, nil]; 

    [myAlert show]; 

} 

+(void)handleNoAccessWithReason:(NSString *)reason { 
    // Standard UIAlert Syntax 
    UIAlertView *myAlert = [[UIAlertView alloc] 
          initWithTitle:@"No Access" 
          message:reason 
          delegate:nil 
          cancelButtonTitle:@"OK" 
          otherButtonTitles:nil, nil]; 

    [myAlert show]; 

} 

@end 

Dies fügt in ein paar Funktionen, die Sie möglicherweise nicht brauchen oder wollen, fühlen Sie sich frei, es zu ändern, wie Sie so lange brauchen Der Abschnitt "Copyright" bleibt bestehen. Ich benutze das APIKey, um die Anfrage zu validieren kam von meiner App und nicht jemand versucht, Dinge zu hacken.

es Calling (vorausgesetzt, Sie NetworkClient.h aufgenommen haben:

NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys: 
          @"ParamValue1", @"ParamName1", 
          @"ParamValue2", @"ParamName2", 
          nil]; 


    [NetworkClient processURLRequestWithURL:nil andParams:params block:^(id obj) { 
     if ([obj isKindOfClass:[NSArray class]]) { 
      // Do whatever you want with the object. In this case, I knew I was expecting an Array, but it will return a Dictionary if that is what the web-service responds with. 
     } 
    }];  

können auch:

NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys: 
          @"ParamValue1", @"ParamName1", 
          nil]; 

    NSString *urlString = @"https://SuppliedURLOverridesDefault"; 
    [NetworkClient processURLRequestWithURL:urlString 
            andParams:params 
           syncRequest:YES 
         alertUserOnFailure:NO 
             block:^(id obj) { 
              if ([obj isKindOfClass:[NSArray class]]) { 
               // Do stuff 
              } 
             }]; 

in einer beliebigen Anzahl von Parametern So nehmen Sie es, injizieren einen apikey oder irgendetwas anderes, wenn Sie wollen und zurück entweder ein Dictionary oder ein Array je nach Web-Service.Dies erwartet SBJson BTW.

+0

EIJay, thx für Ihre Antwort, aber ich möchte AFNetworking Framework verwenden, weil ich weiß, dass es beibehalten wird und besser werden wird. Das ist der Grund, warum ich ASIHTTP verlasse – dormitkon

+0

Die Gründe, warum ich ASI verließ, war, weil AFNetworking Blöcke anstelle von Delegate-Methoden verwendet und weil es nie mit ARC kompatibel sein würde, ohne zu überschreiben. –