Come inviare dati JSON nella richiesta Http usando NSURLRequest

Sono nuovo di objective-c e sto iniziando a mettere un grande sforzo in richiesta / risposta come di recente. Ho un esempio funzionante che può chiamare un url (via http GET) e analizzare il json restituito.

L’esempio funzionante di questo è sotto

- (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]; } 

La mia prima domanda è: questo approccio aumenterà? Oppure non è asincrono (nel senso che blocco il thread dell’interfaccia utente mentre l’app è in attesa della risposta)

La mia seconda domanda è: come posso modificare la parte richiesta di questo per fare un POST al posto di GET? È semplicemente per modificare HttpMethod in questo modo?

 [request setHTTPMethod:@"POST"]; 

E infine – come faccio ad aggiungere un set di dati json a questo post come una semplice stringa (per esempio)

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

Grazie in anticipo

Ecco cosa faccio (tieni presente che il JSON che va sul mio server deve essere un dizionario con un valore (un altro dizionario) per key = question..ie {: question => {dictionary}}):

 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]; } 

Il receivedData viene quindi gestito da:

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

Questo non è chiaro al 100% e richiederà qualche rilettura, ma tutto dovrebbe essere qui per iniziare. E da quello che posso dire, questo è asincrono. La mia interfaccia utente non è bloccata durante queste chiamate. Spero possa aiutare.

Suggerirei di utilizzare ASIHTTPRequest

ASIHTTPRequest è un wrapper facile da usare attorno all’API CFNetwork che rende più semplici gli aspetti più noiosi della comunicazione con i server Web. È scritto in Objective-C e funziona in entrambe le applicazioni Mac OS X e iPhone.

È adatto all’esecuzione di richieste HTTP di base e all’interazione con servizi basati su REST (GET / POST / PUT / DELETE). La sottoclass ASIFormDataRequest inclusa rende facile inviare dati e file POST usando multipart / form-data.


Si prega di notare che l’autore originale ha interrotto questo progetto. Vedi il post seguente per motivi e alternative: http://allseeing-i.com/%5Brequest_release%5D ;

Personalmente sono un grande fan di AFNetworking

Ho lottato con questo per un po ‘. Esecuzione di PHP sul server. Questo codice invierà un json e riceverà la risposta JSON dal server

 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 } }]; 

Molti di voi lo sanno già, ma sto postando questo, solo in caso, alcuni di voi stanno ancora lottando con JSON in iOS6 +.

In iOS6 e versioni successive, la class NSJSONSerialization è veloce e non ha alcuna dipendenza dall’inclusione di librerie “esterne”.

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

Questo è il modo in cui iOS6 e versioni successive possono ora analizzare JSON in modo efficiente. L’uso di SBJson è anche un’implementazione pre-ARC e porta con sé anche questi problemi se si sta lavorando in un ambiente ARC.

Spero che aiuti!

Ecco un ottimo articolo che utilizza il Restkit

Spiega sulla serializzazione dei dati annidati in JSON e allegando i dati a una richiesta POST HTTP.

Poiché la mia modifica alla risposta di Mike G per modernizzare il codice è stata respinta dal 3 al 2 come

Questa modifica aveva lo scopo di indirizzare l’autore del post e non ha senso come una modifica. Dovrebbe essere stato scritto come commento o risposta

Sto rimappando la mia modifica come risposta separata qui. Questa modifica rimuove la dipendenza JSONRepresentation con NSJSONSerialization come NSJSONSerialization il commento di Rob con 15 upvotes.

  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]; } 

Il receivedData viene quindi gestito da:

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

Ecco un esempio aggiornato che utilizza NSURLConnection + sendAsynchronousRequest: (10.7+, iOS 5+), La richiesta “Post” rimane la stessa della risposta accettata e viene omessa qui per motivi di chiarezza:

 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); } } }]; 

Puoi provare questo codice per mandare la stringa 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];