2010-12-16 171 views
76

Je suis novice en ce qui concerne l'objectif-c et je commence à mettre beaucoup d'efforts dans la demande/réponse depuis peu. J'ai un exemple de travail qui peut appeler une url (via http GET) et analyser le json retourné.Comment envoyer des données json dans la requête Http en utilisant NSURLRequest

L'exemple de travail de ce qui est inférieur

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

Ma première question est - cette approche va évoluer jusqu'à? Ou est-ce pas async (ce qui signifie que je bloque le thread UI pendant que l'application attend la réponse)

Ma deuxième question est - comment puis-je modifier la partie de la demande pour faire un POST au lieu de GET? Est-ce simplement pour modifier le HttpMethod comme ça?

[request setHTTPMethod:@"POST"]; 

Et enfin - comment puis-je ajouter un ensemble de données JSON à ce poste comme une simple chaîne (par exemple)

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

Nous vous remercions à l'avance

+1

Voici un tutoriel: http: // mobileorchard .com/tutorial-json-sur-http-sur-le-iphone/ – Josh

Répondre

101

Voici ce que je (s'il vous plaît note que le JSON va à mon serveur doit être un dictionnaire avec une valeur (autre dictionnaire) pour key = {question..ie : question => {dictionnaire}}):

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

Le receivedData est alors gérée par:

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

Ce n'est pas 100% clair et prendra un certain re-lecture , mais tout devrait être là pour vous aider à démarrer. Et d'après ce que je peux dire, c'est asynchrone. Mon interface utilisateur n'est pas bloquée pendant que ces appels sont faits. J'espère que cela pourra aider.

+0

Tout semble bon sauf la ligne this [dict objectForKey: @ "user_question"], nil]; - dict n'est pas déclaré dans votre échantillon. Est-ce juste un dictionnaire simple ou quelque chose de spécial? –

+1

Désolé à ce sujet. Oui, "dict" est juste un simple dictionnaire que je charge à partir des documents des utilisateurs iOS. –

+17

Ceci utilise la méthode d'instance 'NSDictionary'' JSONRepresentation'. Je pourrais suggérer d'utiliser la méthode de classe 'NSWSONSerialization'' dataWithJSONObject', au lieu de [json-framework] (https://github.com/stig/json-framework/). – Rob

6

Je suggère d'utiliser ASIHTTPRequest

ASIHTTPRequest est un outil facile à utiliser wrapper autour de l'API qui CFNetwork rend certains des aspects les plus fastidieux de communiquer avec les serveurs Web plus facile. Il est écrit en Objective-C et fonctionne à la fois dans les applications Mac OS X et iPhone .

Il convient d'effectuer des demandes HTTP de base et coopérant avec services REST (GET/POST/PUT /DELETE). La sous-classe ASIFormDataRequest incluse permet de soumettre facilement les données POST et les fichiers en utilisant multipart/form-data.


S'il vous plaît noter que l'auteur original interrompu ce projet. Voir le message suivant pour les raisons et les alternatives: http://allseeing-i.com/%5Brequest_release%5D;

Personnellement, je suis un grand fan de AFNetworking

+0

@Almo, vous n'avez pas lu l'article entier, avez-vous? – vikingosegundo

+0

Duh, je ne l'ai pas fait. Pardon. – Almo

2

Voici un article à l'aide Restkit

Il explique sur sérialisation des données imbriquées dans JSON et attacher les données à une requête HTTP POST.

3

La plupart d'entre vous le savent déjà, mais je publie ceci, juste au cas où certains d'entre vous sont encore aux prises avec JSON dans iOS6 +.

Dans iOS6 et versions ultérieures, nous avons le NSJSONSerialization Class qui est rapide et dépourvu de dépendance à l'égard des bibliothèques «externes».

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

C'est la façon iOS6 et plus tard peut maintenant analyser l'utilisation JSON efficiently.The de SBJson est également mise en œuvre pré-ARC et apporte avec lui ces questions aussi, si vous travaillez dans un environnement ARC.

J'espère que cela aide!

0

Voici un exemple mis à jour qui utilise NSURLConnection + sendAsynchronousRequest: (10.7+, iOS 5+), la demande « Post » reste le même que la réponse acceptée et est omise ici par souci de clarté:

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 question était au sujet de POST – ahmad

+2

non, la première partie de la question est sur l'asynchronicité et il n'y a pas de réponse ici qui répond à cela. Salutations pour le downvote. – auco

6

J'ai lutté avec cela pendant un moment. Exécuter PHP sur le serveur. Ce code affichera un JSON et obtenir la réponse JSON du serveur

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

type de contenu = "application/x-www-form-urlencoded" a fait l'affaire. Merci – SamChen

+0

Bonne réponse. J'ai utilisé "application/json" dans mon cas –

2

Depuis mon édition à la réponse de Mike G pour moderniser le code a été rejeté 3 à 2 comme

Cette modification était destinée à répondre l'auteur de la publication et ne fait aucun sens comme un edit. Il aurait dû être écrit comme un commentaire ou une réponse

Je reposter mon édition comme une réponse distincte ici. Cette modification supprime la dépendance JSONRepresentation avec NSJSONSerialization comme le suggère le commentaire de Rob avec 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]; 
    } 

Le receivedData est alors géré par:

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

Vous pouvez essayer ce code pour envoyer la chaîne 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];