Frage So senden Sie Json-Daten in der HTTP-Anfrage mit NSURLRequest


Ich bin neu bei objective-c und ich fange an, eine Menge Mühe in die Anfrage / Antwort zu investieren. Ich habe ein funktionierendes Beispiel, das eine URL (über http GET) aufrufen und den zurückgegebenen JSON analysieren kann.

Das Arbeitsbeispiel hierfür ist unten

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

Meine erste Frage ist - wird dieser Ansatz erweitert? Oder ist das nicht asynchron (dh ich blockiere den UI-Thread, während die App auf die Antwort wartet)

Meine zweite Frage ist - wie kann ich den Anfrageteil davon modifizieren, um einen POST statt GET zu machen? Ist es einfach, die HttpMethod so zu modifizieren?

[request setHTTPMethod:@"POST"];

Und schließlich - wie füge ich eine Menge von Json-Daten zu diesem Beitrag als eine einfache Zeichenfolge (zum Beispiel)

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

Vielen Dank im Voraus


76
2017-12-16 02:30


Ursprung


Antworten:


Hier ist, was ich mache (bitte beachten Sie, dass das JSON, das auf meinen Server geht, ein Wörterbuch mit einem Wert (ein anderes Wörterbuch) für key = question..i.e. {: Question => {dictionary}}) sein muss:

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

Die receivedData wird dann behandelt von:

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

Dies ist nicht 100% klar und wird ein wenig neu gelesen werden, aber alles sollte hier sein, um loszulegen. Und von dem, was ich sagen kann, ist das asynchron. Meine Benutzeroberfläche ist nicht gesperrt, während diese Anrufe getätigt werden. Ich hoffe, das hilft.


101
2017-12-17 01:11



Ich würde vorschlagen, zu verwenden ASIHTTPAnfrage

ASIHTTPRequest ist einfach zu benutzen   Wrapper um die CFNetwork-API, die   macht einige der langweiligeren Aspekte   der Kommunikation mit Webservern   einfacher. Es ist in Objective-C geschrieben   und funktioniert sowohl in Mac OS X als auch in iPhone   Anwendungen.

Es ist geeignet, einfaches HTTP auszuführen   Anfragen und Interaktion mit   REST-basierte Dienste (GET / POST / PUT   / LÖSCHEN). Das inbegriffene   ASIFormDataRequest-Unterklasse macht es   Einfach zu übermitteln POST-Daten und Dateien   Verwenden von mehrteiligen / Formulardaten.


Bitte beachten Sie, dass der ursprüngliche Autor dieses Projekt eingestellt hat. Siehe den folgenden Beitrag für Gründe und Alternativen: http://allseeing-i.com/%5Bestquest_release%5D;

Persönlich bin ich ein großer Fan von AFNetworking


6
2017-12-16 02:33



Ich kämpfte eine Weile damit. Ausführen von PHP auf dem Server Dieser Code wird einen JSON veröffentlichen und die JSON-Antwort vom Server erhalten

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

     }
 }];

6
2018-02-11 15:03



Die meisten von euch wissen das schon jetzt, aber ich poste dies, nur weil einige von euch immer noch mit JSON in iOS6 + zu kämpfen haben.

In iOS6 und später haben wir die NSJSONSerialization-Klasse das ist schnell und hängt nicht davon ab, "externe" Bibliotheken einzubeziehen.

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

Auf diese Weise können iOS6 und höher JSON effizient parsen. Die Verwendung von SBJson ist auch eine Vor-ARC-Implementierung und bringt diese Probleme mit sich, wenn Sie in einer ARC-Umgebung arbeiten.

Ich hoffe das hilft!


3
2017-11-12 14:49



Hier ist ein toller Artikel mit Restkit

Es wird erläutert, wenn verschachtelte Daten in JSON serialisiert und die Daten an eine HTTP-POST-Anforderung angehängt werden.


2
2017-08-19 16:34



Seit meiner Bearbeitung zu Mike G's Antwort wurde der Code 3 zu 2 als abgelehnt

Diese Änderung sollte den Autor des Posts ansprechen und macht nein   Sinn als Bearbeitung. Es hätte als Kommentar oder als Kommentar geschrieben werden sollen   Antworten

Ich wiederhole meine Bearbeitung als separate Antwort hier. Diese Änderung entfernt die JSONRepresentation Abhängigkeit mit NSJSONSerialization wie Robs Kommentar mit 15 upvotes suggeriert.

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

Die receivedData wird dann behandelt von:

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

2
2017-11-03 17:54



Hier ist ein aktualisiertes Beispiel, das NSURLConnection + sendAsynchronousRequest verwendet: (10.7+, iOS 5+), Die "Post" -Anfrage bleibt dieselbe wie bei der akzeptierten Antwort und wird hier aus Gründen der Klarheit weggelassen:

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
2017-12-09 14:42