2010-12-16 18 views
76

Soy nuevo en el objetivo-c y estoy comenzando a poner mucho esfuerzo en la solicitud/respuesta en fecha reciente. Tengo un ejemplo de trabajo que puede llamar a una url (a través de http GET) y analizar el json devuelto.Cómo enviar datos json en la solicitud Http usando NSURLRequest

El ejemplo práctico de esto es por debajo de

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 
    [responseData setLength:0]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    [responseData appendData:data]; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    NSLog([NSString stringWithFormat:@"Connection failed: %@", [error description]]); 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    [connection release]; 
    //do something with the json that comes back ... (the fun part) 
} 

- (void)viewDidLoad 
{ 
    [self searchForStuff:@"iPhone"]; 
} 

-(void)searchForStuff:(NSString *)text 
{ 
    responseData = [[NSMutableData data] retain]; 
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.whatever.com/json"]]; 
    [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
} 

Mi primera pregunta es - escalará hasta este enfoque? ¿O no es asincrónico (es decir, bloqueo el hilo de la interfaz de usuario mientras la aplicación está esperando la respuesta)

Mi segunda pregunta es: ¿cómo podría modificar la parte de la solicitud para hacer una POST en lugar de GET? ¿Es simplemente modificar HttpMethod como tal?

[request setHTTPMethod:@"POST"]; 

Y finalmente - ¿cómo puedo añadir un conjunto de datos JSON para este post como una cadena sencilla (por ejemplo)

{ 
    "magic":{ 
       "real":true 
      }, 
    "options":{ 
       "happy":true, 
       "joy":true, 
       "joy2":true 
       }, 
    "key":"123" 
} 

gracias de antemano

+1

Aquí hay un tutorial: http: // mobileorchard .com/tutorial-json-over-http-on-the-iphone/ – Josh

Respuesta

101

Esto es lo que hago (Tenga en cuenta que el JSON ir a mi servidor tiene que ser un diccionario con un valor (otro diccionario) para la tecla = {question..ie : pregunta => {}} diccionario):

NSArray *objects = [NSArray arrayWithObjects:[[NSUserDefaults standardUserDefaults]valueForKey:@"StoreNickName"], 
    [[UIDevice currentDevice] uniqueIdentifier], [dict objectForKey:@"user_question"],  nil]; 
NSArray *keys = [NSArray arrayWithObjects:@"nick_name", @"UDID", @"user_question", nil]; 
NSDictionary *questionDict = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; 

NSDictionary *jsonDict = [NSDictionary dictionaryWithObject:questionDict forKey:@"question"]; 

NSString *jsonRequest = [jsonDict JSONRepresentation]; 

NSLog(@"jsonRequest is %@", jsonRequest); 

NSURL *url = [NSURL URLWithString:@"https://xxxxxxx.com/questions"]; 

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url 
      cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; 


NSData *requestData = [jsonRequest dataUsingEncoding:NSUTF8StringEncoding]; 

[request setHTTPMethod:@"POST"]; 
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 
[request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"]; 
[request setHTTPBody: requestData]; 

NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self]; 
if (connection) { 
receivedData = [[NSMutableData data] retain]; 
} 

El receivedData continuación, se maneja por:

NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
NSDictionary *jsonDict = [jsonString JSONValue]; 
NSDictionary *question = [jsonDict objectForKey:@"question"]; 

Esto no es 100% claro y tomará algún relectura , pero todo debería estar aquí para que comiences. Y por lo que puedo decir, esto es asincrónico. Mi UI no está bloqueada mientras se realizan estas llamadas. Espero que ayude.

+0

Todo se ve bien excepto la línea [dict objectForKey: @ "user_question"], nil]; - dict no está declarado en tu muestra. ¿Es esto solo un diccionario simple o algo especial? –

+1

Lo siento. Sí, "dict" es solo un diccionario simple que cargo desde los documentos de los usuarios de iOS. –

+17

Esto está usando el método de instancia 'NSDictionary'' JSONRepresentation'. Podría sugerir que use el método de clase 'NSJSONSerialization'' dataWithJSONObject', en lugar de [json-framework] (https://github.com/stig/json-framework/). – Rob

6

sugeriría a utilizar ASIHTTPRequest

ASIHTTPRequest es una herramienta fácil de usar contenedor del API que CFNetwork hace que algunos de los aspectos más tediosos de la comunicación con los servidores web más fácil. Está escrito en Objective-C y funciona en las aplicaciones Mac OS X e iPhone .

Es adecuado realizar HTTP básico solicitudes e interactuar con servicios basados ​​en REST (GET/POST/PUT /DELETE). La subclase ASIFormDataRequest incluida lo hace fácil de enviar datos POST y archivos usando multipart/form-data.


Tenga en cuenta, que el autor original suspendió con este proyecto. Consulte la publicación siguiente por razones y alternativas: http://allseeing-i.com/%5Brequest_release%5D;

Personalmente soy un gran fan de AFNetworking

+0

@Almo, no leíste toda la publicación, ¿o sí? – vikingosegundo

+0

Duh, no lo hice. Lo siento. – Almo

2

Aquí es un gran artículo usando Restkit

En él se explica en la serialización de datos anidados en JSON y adjuntar los datos a una petición HTTP POST.

3

La mayoría de ustedes ya saben esto, pero estoy publicando esto, solo por si acaso, algunos de ustedes aún están luchando con JSON en iOS6 +.

En iOS6 y posterior, tenemos el NSJSONSerialization Class que es rápido y no tiene ninguna dependencia de incluir bibliotecas "externas".

NSDictionary *result = [NSJSONSerialization JSONObjectWithData:[resultStr dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; 

Esta es la forma en iOS 6 y más tarde ahora puede analizar el uso de JSON efficiently.The de SBJson es también la aplicación de pre-ARC y trae consigo esas cuestiones también si se está trabajando en un entorno ARC.

Espero que esto ayude!

0

He aquí un ejemplo actualizado que está utilizando NSURLConnection + sendAsynchronousRequest: (10.7 o versiones posteriores, iOS 5+), La solicitud "Post" sigue siendo el mismo que con la respuesta aceptada y se omite aquí en aras de la claridad:

NSURL *apiURL = [NSURL URLWithString: 
    [NSString stringWithFormat:@"http://www.myserver.com/api/api.php?request=%@", @"someRequest"]]; 
NSURLRequest *request = [NSURLRequest requestWithURL:apiURL]; // this is using GET, for POST examples see the other answers here on this page 
[NSURLConnection sendAsynchronousRequest:request 
            queue:[NSOperationQueue mainQueue] 
         completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { 
    if(data.length) { 
     NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
     if(responseString && responseString.length) { 
      NSLog(@"%@", responseString); 
     } 
    } 
}]; 
+0

la pregunta fue sobre POST – ahmad

+2

no, la primera parte de la pregunta es sobre asincronicidad y no hay respuesta aquí que responda eso. Saludos por el downvote. – auco

6

Luché con esto por un tiempo. Ejecutando PHP en el servidor. Este código será publicar un JSON y obtener la respuesta JSON desde el servidor

NSURL *url = [NSURL URLWithString:@"http://example.co/index.php"]; 
NSMutableURLRequest *rq = [NSMutableURLRequest requestWithURL:url]; 
[rq setHTTPMethod:@"POST"]; 
NSString *post = [NSString stringWithFormat:@"command1=c1&command2=c2"]; 
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding]; 
[rq setHTTPBody:postData]; 
[rq setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 

[NSURLConnection sendAsynchronousRequest:rq queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) 
{ 
    if ([data length] > 0 && error == nil){ 
     NSError *parseError = nil; 
     NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError]; 
     NSLog(@"Server Response (we want to see a 200 return code) %@",response); 
     NSLog(@"dictionary %@",dictionary); 
    } 
    else if ([data length] == 0 && error == nil){ 
     NSLog(@"no data returned"); 
     //no data, but tried 
    } 
    else if (error != nil) 
    { 
     NSLog(@"there was a download error"); 
     //couldn't download 

    } 
}]; 
+1

content type = "application/x-www-form-urlencoded" hizo el truco. Gracias – SamChen

+0

Nice answer. Utilicé "application/json" en mi caso –

2

Desde mi edición de la respuesta de Mike G para modernizar el código fue rechazada 3 a 2 como

esta edición se pretende abordar el autor de la publicación y no hace sentido como una edición. Debería haber sido escrito como un comentario o una respuesta

Estoy volviendo a publicar mi edición como una respuesta separada aquí. Esta edición elimina la dependencia JSONRepresentation con NSJSONSerialization, como sugiere el comentario de Rob con 15 votos ascendentes.

NSArray *objects = [NSArray arrayWithObjects:[[NSUserDefaults standardUserDefaults]valueForKey:@"StoreNickName"], 
     [[UIDevice currentDevice] uniqueIdentifier], [dict objectForKey:@"user_question"],  nil]; 
    NSArray *keys = [NSArray arrayWithObjects:@"nick_name", @"UDID", @"user_question", nil]; 
    NSDictionary *questionDict = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; 

    NSDictionary *jsonDict = [NSDictionary dictionaryWithObject:questionDict forKey:@"question"]; 

    NSLog(@"jsonRequest is %@", jsonRequest); 

    NSURL *url = [NSURL URLWithString:@"https://xxxxxxx.com/questions"]; 

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url 
       cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; 


    NSData *requestData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil]; //TODO handle error 

    [request setHTTPMethod:@"POST"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 
    [request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"]; 
    [request setHTTPBody: requestData]; 

    NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self]; 
    if (connection) { 
    receivedData = [[NSMutableData data] retain]; 
    } 

El receivedData continuación, se maneja por:

NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 
    NSDictionary *question = [jsonDict objectForKey:@"question"]; 
0

Puede probar este código de texto enviado JSON

NSData *jsonData = [NSJSONSerialization dataWithJSONObject:ARRAY_CONTAIN_JSON_STRING options:NSJSONWritin*emphasized text*gPrettyPrinted error:NULL]; 
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 
NSString *WS_test = [NSString stringWithFormat:@"www.test.com?xyz.php&param=%@",jsonString]; 
Cuestiones relacionadas