iphone - consumir servicio rest swift 4
Cómo enviar datos json en la solicitud Http usando NSURLRequest (8)
Soy nuevo en Objectivo-c y estoy empezando a poner mucho esfuerzo en la solicitud / respuesta como reciente. Tengo un ejemplo de trabajo que puede llamar a una url (a través de http GET) y analizar el json devuelto.
El ejemplo de trabajo de esto está debajo
- (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: ¿se ampliará 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 de esto para hacer una POST en lugar de GET? ¿Es simplemente modificar HttpMethod como tal?
[request setHTTPMethod:@"POST"];
Y finalmente, ¿cómo agrego un conjunto de datos json a esta publicación como una cadena simple (por ejemplo)
{
"magic":{
"real":true
},
"options":{
"happy":true,
"joy":true,
"joy2":true
},
"key":"123"
}
Gracias de antemano
Puede probar este código para enviar cadena 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¶m=%@",jsonString];
Aquí hay un ejemplo actualizado que está usando NSURLConnection + sendAsynchronousRequest: (10.7+, iOS 5+), la solicitud "Publicar" sigue siendo la misma 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);
}
}
}];
Aquí hay un gran artículo usando Restkit
Explica sobre la serialización de datos anidados en JSON y la conexión de los datos a una solicitud HTTP POST.
Desde mi edición a la respuesta de Mike G para modernizar el código fue rechazado 3 a 2 como
Esta edición tenía como objetivo dirigirse al autor de la publicación y no tiene sentido como una edición. Debería haber sido escrito como un comentario o una respuesta
Estoy reubicando mi edición como una respuesta separada aquí. Esta edición elimina la dependencia JSONRepresentation
con NSJSONSerialization
como NSJSONSerialization
el comentario de 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];
}
El receivedData es manejado por:
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSDictionary *question = [jsonDict objectForKey:@"question"];
Esto es lo que hago (tenga en cuenta que el JSON que va a mi servidor necesita ser un diccionario con un valor (otro diccionario) para 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];
}
El receivedData es manejado 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á algunas relecturas, pero todo debería estar aquí para comenzar. Y por lo que puedo decir, esto es asincrónico. Mi UI no está bloqueada mientras se realizan estas llamadas. Espero que ayude.
La mayoría de ustedes ya saben esto, pero estoy publicando esto, solo en el caso, algunos de ustedes todavía están luchando con JSON en iOS6 +.
En iOS6 y posterior, tenemos la clase NSJSONSerialization que es rápida y no tiene dependencia de incluir bibliotecas "externas".
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:[resultStr dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
Esta es la forma en que iOS6 y posterior ahora pueden analizar JSON de manera eficiente. El uso de SBJson también es una implementación previa al ARC y trae consigo esos problemas también si está trabajando en un entorno ARC.
¡Espero que esto ayude!
Luché con esto por un tiempo. Ejecutando PHP en el servidor. Este código publicará un json y obtendrá la respuesta json del 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
}
}];
Sugeriría usar ASIHTTPRequest
ASIHTTPRequest es un contenedor fácil de usar alrededor de la API de CFNetwork que facilita algunos de los aspectos más tediosos de la comunicación con servidores web. Está escrito en Objective-C y funciona en aplicaciones Mac OS X e iPhone.
Es adecuado realizar solicitudes HTTP básicas e interactuar con servicios basados en REST (GET / POST / PUT / DELETE). La subclase ASIFormDataRequest incluida facilita el envío de datos POST y archivos usando multipart / form-data.
Tenga en cuenta que el autor original suspendió este proyecto. Consulte la publicación siguiente por motivos y alternativas: http://allseeing-i.com/%5Brequest_release%5D ;
Personalmente, soy un gran fanático de AFNetworking