Jestem nowy w celu-c i zaczynam wkładać dużo wysiłku w prośby / odpowiedzi od niedawna. Mam działający przykład, który może wywołać adres URL (przez http GET) i przeanalizować zwrócony plik json.
Roboczy przykład tego znajduje się poniżej
- (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];
}
Moje pierwsze pytanie brzmi - czy to podejście będzie się rozwijać? Czy to nie jest asynchroniczne (co oznacza, że blokuję wątek interfejsu użytkownika, gdy aplikacja czeka na odpowiedź)
Moje drugie pytanie brzmi - jak mogę zmodyfikować część żądania, aby wykonać POST zamiast GET? Czy wystarczy zmodyfikować HttpMethod w ten sposób?
[request setHTTPMethod:@"POST"];
I na koniec - jak dodać zestaw danych json do tego postu jako prosty ciąg (na przykład)
{
"magic":{
"real":true
},
"options":{
"happy":true,
"joy":true,
"joy2":true
},
"key":"123"
}
Z góry dziękuję
iphone
objective-c
cocoa-touch
json
nsurlrequest
Toran Billups
źródło
źródło
Odpowiedzi:
Oto, co robię (pamiętaj, że JSON przechodzący na mój serwer musi być słownikiem z jedną wartością (innym słownikiem) dla klucza = pytanie..ie {: question => {słownik}}):
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]; }
Otrzymane dane są następnie obsługiwane przez:
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSDictionary *jsonDict = [jsonString JSONValue]; NSDictionary *question = [jsonDict objectForKey:@"question"];
Nie jest to w 100% jasne i będzie wymagało ponownego przeczytania, ale wszystko powinno być tutaj, aby zacząć. Z tego, co wiem, jest to asynchroniczne. Mój interfejs użytkownika nie jest zablokowany podczas wykonywania tych połączeń. Mam nadzieję, że to pomoże.
źródło
NSDictionary
metody instancjiJSONRepresentation
. Mogę zasugerować użycieNSJSONSerialization
metody klasydataWithJSONObject
zamiast frameworka json .[[NSNumber numberWithUnsignedInt:requestData.length] stringValue]
.Walczyłem z tym przez chwilę. Uruchamianie PHP na serwerze. Ten kod wyśle json i otrzyma odpowiedź json z serwera
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 } }];
źródło
Sugerowałbym użycie ASIHTTPRequest
Należy pamiętać, że oryginalny autor przerwał ten projekt. Zobacz następujący post z przyczynami i alternatywami: http://allseeing-i.com/%5Brequest_release%5D ;
Osobiście jestem wielkim fanem AFNetworking
źródło
Większość z was już to wie, ale piszę o tym, na wszelki wypadek, niektórzy z was wciąż zmagają się z JSON w iOS6 +.
W iOS6 i późniejszych mamy klasę NSJSONSerialization, która jest szybka i nie ma zależności od dołączania bibliotek „zewnętrznych”.
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:[resultStr dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
W ten sposób iOS6 i nowsze wersje mogą teraz wydajnie analizować JSON. Użycie SBJson jest również implementacją przed ARC i niesie ze sobą również te problemy, jeśli pracujesz w środowisku ARC.
Mam nadzieję, że to pomoże!
źródło
Oto świetny artykuł dotyczący korzystania z Restkit
Wyjaśnia serializowanie zagnieżdżonych danych do formatu JSON i dołączanie danych do żądania HTTP POST.
źródło
Ponieważ moja edycja odpowiedzi Mike'a G dotycząca modernizacji kodu została odrzucona 3 do 2 jako
Ponownie publikuję tutaj moją zmianę jako osobną odpowiedź. Ta zmiana usuwa
JSONRepresentation
zależność z,NSJSONSerialization
jak sugeruje komentarz Roba z 15 pozytywnymi opiniami.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]; }
Otrzymane dane są następnie obsługiwane przez:
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; NSDictionary *question = [jsonDict objectForKey:@"question"];
źródło
Oto zaktualizowany przykład korzystający z NSURLConnection + sendAsynchronousRequest: (10.7+, iOS 5+). Żądanie „Post” pozostaje takie samo, jak w przypadku zaakceptowanej odpowiedzi i zostało tutaj pominięte ze względu na przejrzystość:
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); } } }];
źródło
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¶m=%@",jsonString];
źródło