entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

1voto

PHP Webservice + JSON + iOS+MySQL

Buenas tardes a todos,

Tengo un pequeño problema. Actualmente dispongo de una aplicacion en Android la cual tiene 4 pantallas y dichas pantallas se cargan desde una base de datos en MySQL y tienen acceso a modificar esa base de datos. El sistema esta montado con un webservice el cual se encarga de hacer las consultas a la base de datos usando if, es decir, si desde el JSON le paso como parámetro method el method "delete" elimina el registro y si le paso "list" me lista los registros. Todo me funciona perfectamente pero ahora tengo que hacer la misma aplicación para iOS y no encuentro ningún sitio donde te explique como hacerlo. Si que te explican como hacerlo si al llamar directamente a la URL te devuelve el valor, pero no ha hacer consultas.

Un ejemplo del código que hago servir para eliminar un registro es el siguiente:
En la clase de Java:

public class ServerAccess {

public static String convertStreamToString(InputStream is) {
    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    StringBuilder sb = new StringBuilder();

    String line = null;
    try {
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
    } catch (IOException e) {
        Log.e("PHP Client", "Error : " + e.getMessage());
    } finally {
        try {
            is.close();
        } catch (IOException e1) {
            Log.e("PHP Client", "Error : " + e1.getMessage());
        }
    }
    return sb.toString();
}

public Object getResponseObject(ArrayList Parameters, Class c) {

    try {

        HttpClient httpclient = new DefaultHttpClient();

        HttpPost httppost = new HttpPost(Constants.SERVICE_URL);

        httppost.setEntity(new UrlEncodedFormEntity(Parameters));

        HttpResponse response = httpclient.execute(httppost);

        HttpEntity entity = response.getEntity();

        InputStream stream = entity.getContent();

        String result = convertStreamToString(stream);

        Gson gson = new Gson();

        Object responseObject = gson.fromJson(result, c);

        return responseObject;
    } catch (Exception e) {
        Log.e("PHP Client", "Error in http connection" + e.toString());
        return null;
    }
}
public void setEliminarReserva(String code) {
    ArrayList parameters = new ArrayList();
    parameters.add(new BasicNameValuePair("method", "setEliminarReserva"));
    parameters.add(new BasicNameValuePair("code", code));
    setData(parameters);
}

Y en el fichero .php:

 if($Request_Method=="setEliminarReserva")

 {

$code=$_REQUEST['code'];
$query = "DELETE FROM `u738720968_p01`.`booking` WHERE `booking`.`code`='$code'" or die(mysql_error());
if ($query) {
        echo "Datos borrados correctamente";
    } else {
        echo "Error al borrar los datos";
    }

$result = mysql_query($query);

while($row = mysql_fetch_assoc($result))
{
    $resultArray[] = $row;
}

echo json_encode($resultArray);
 }

Lo que necesitaría es saber desde 0 como programar el parser desde iOS.

Muchas gracias por adelantado

2 Respuestas

2votos

juancruzmdq Puntos1500

Como estas Victor?
Te puedo recomendar que veas este framework, te va a simplificar mucho la vida
http://afnetworking.com/
En la documentación vas a encontrar muchos ejemplos.

Tambien te puede ser util https://github.com/johnezang/JSONKit para trabajar con JSON.

Suerte

0voto

victor_capilla comentado

Muchísimas gracias!
La verdad es que si en Android me molestaba que si querías compatibilidad con todos los dispositivos había métodos que estaban obsoletos, en iOS me esta asando de la 5 a la 6! Y hay muy poco cosa de 6 en conexiones JSON. Probarle el framework que me has facilitado y así también aprendo a manejarme con frameworks en iOS.

Mil Gracias de nuevo, te digo algo cuando lo haya probado!

-1voto

juancruzmdq comentado

Dar soporte a IOS5 es importante para tu proyecto?
Fijate estos porcentajes de dispositivos con IOS5 y IOS6, se justifica que des soporte a IOS5?
http://mxapple.com.mx/wp/el-93-de-los-usuarios-totales-de-ios-poseen-ios-6/
Ademas dentro de poco viene IOS7, los porcentajes van a seguir bajando.

Saludos

0voto

victor_capilla comentado

Lo entiendo, pero si busco soluciones y todo lo que encuentro es para iOS 5 y muxas de las cosas que encuenteo y pruebo en 6.1 me lo marca como si no existiera como el method diccionaryWithJsonData... aunque lo mejor es diseñarlo todo para la ultima version

0voto

juancruzmdq comentado

Te sirvio alguna de estas respuestas?

0voto

victor_capilla comentado

Llevo toda esta semana con un problema con AFNetworking. Solo adjuntando la carpeta al proyecto me saltan mensajes de error de la clase AFHTTPClient:

Undefined symbols for architecture i386:
  "_SecCertificateCopyData", referenced from:
      -[AFURLConnectionOperation connection:willSendRequestForAuthenticationChallenge:] in AFURLConnectionOperation.o
  "_SecCertificateCreateWithData", referenced from:
      ___44+[AFURLConnectionOperation pinnedPublicKeys]_block_invoke in AFURLConnectionOperation.o
  "_SecPolicyCreateBasicX509", referenced from:
      ___44+[AFURLConnectionOperation pinnedPublicKeys]_block_invoke in AFURLConnectionOperation.o
      -[AFURLConnectionOperation connection:willSendRequestForAuthenticationChallenge:] in AFURLConnectionOperation.o
  "_SecTrustCopyPublicKey", referenced from:
      ___44+[AFURLConnectionOperation pinnedPublicKeys]_block_invoke in AFURLConnectionOperation.o
      -[AFURLConnectionOperation connection:willSendRequestForAuthenticationChallenge:] in AFURLConnectionOperation.o
  "_SecTrustCreateWithCertificates", referenced from:
      ___44+[AFURLConnectionOperation pinnedPublicKeys]_block_invoke in AFURLConnectionOperation.o
      -[AFURLConnectionOperation connection:willSendRequestForAuthenticationChallenge:] in AFURLConnectionOperation.o
  "_SecTrustEvaluate", referenced from:
      ___44+[AFURLConnectionOperation pinnedPublicKeys]_block_invoke in AFURLConnectionOperation.o
      -[AFURLConnectionOperation connection:willSendRequestForAuthenticationChallenge:] in AFURLConnectionOperation.o
  "_SecTrustGetCertificateAtIndex", referenced from:
      -[AFURLConnectionOperation connection:willSendRequestForAuthenticationChallenge:] in AFURLConnectionOperation.o
  "_SecTrustGetCertificateCount", referenced from:
      -[AFURLConnectionOperation connection:willSendRequestForAuthenticationChallenge:] in AFURLConnectionOperation.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

1voto

juancruzmdq comentado

agregaste estos dos framework?
CFNetwork.framework y Security.framework

supongo que te falta agregar Security.framework al proyecto

0voto

victor_capilla comentado

Ok, donde lo importo, en el fichero pch?

-1voto

juancruzmdq comentado

Fijate por aca, google siempre es una buena opcion

https://www.google.com.ar/search?q=xcode+incluir+framework

0voto

victor_capilla comentado

Perfecto, ya he conseguido que el proyecto compile y se ejecute, pero sigue sin funcionar. Os muestro lo que he puesto:

 NSString *weatherUrl = [NSString stringWithFormat:@"%@?method=getBooking", BaseURLString];
    NSURL *url = [NSURL URLWithString:weatherUrl];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    AFJSONRequestOperation *operation =
    [AFJSONRequestOperation JSONRequestOperationWithRequest:request

                                                    success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
                                                        self.weather  = (NSDictionary *)JSON;
                                                        self.title = @"JSON Retrieved";
                                                        [self.tableView reloadData];
                                                    }

                                                    failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
                                                        UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Error Retrieving Weather"
                                                                                                     message:[NSString stringWithFormat:@"%@",error]
                                                                                                    delegate:nil
                                                                                           cancelButtonTitle:@"OK" otherButtonTitles:nil];
                                                        [av show];
                                                    }];

    [operation start];

El problema es que en mi fichero PHP no estoy usando un GET ni un post lo que hago es lo siguiente:

 $Request_Method=$_REQUEST['method'] or die('Method name not found');

 //Conectar con la base de datos
 $Connection = mysql_connect("") or die('Cannot connect to Database');

 //Seleccionar la base de datos
 mysql_select_db("") or die('Cannot select Database');

 //getBooking - Obtener todos los códigos que coinciden con el codigo que le pasemos
 if($Request_Method=="getBooking")
 {
    $code=$_REQUEST['code'];
    $query="SELECT code FROM booking where LEFT(code,6)='$code' ";

    $result = mysql_query($query);

    while($row = mysql_fetch_assoc($result))
    {
        $resultArray[] = $row;
    }

    echo json_encode($resultArray);
 }

Como indico en la URL que quiero pasarle como method = getBooking y como code el 123456?

0voto

juancruzmdq comentado

Al usar $_REQUEST, indirectamente estas usando $_GET, $_POST o $_COOKIE
http://php.net/manual/es/reserved.variables.request.php

Si no funciona algún error te tiene que estar informando. que resultado tenes para decir que no funciona?

0voto

victor_capilla comentado

Si yo le envio la URL asi:

NSString *weatherUrl = [NSString stringWithFormat:@"%@?method=getBooking&code=220513", BaseURLString];

Me retorna este error

2013-09-16 09:47:05.976 Weather[450:c07] Error Domain=AFNetworkingErrorDomain Code=-1016 "Expected content type {(
    "text/json",
    "application/json",
    "text/javascript"
)}, got text/html" UserInfo=0x7b19db0 {NSLocalizedRecoverySuggestion=[{"code":"22051310"},{"code":"22051311"},{"code":"22051312"},{"code":"22051313"}]
, AFNetworkingOperationFailingURLRequestErrorKey=<NSURLRequest http://natursais.tk/testservice.php?method=getBooking&code=220513>, NSErrorFailingURLKey=http://natursais.tk/testservice.php?method=getBooking&code=220513, NSLocalizedDescription=Expected content type {(
    "text/json",
    "application/json",
    "text/javascript"
)}, got text/html, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0x7e35810>}

-1voto

juancruzmdq comentado

0voto

victor_capilla comentado

Hasta ahi llego... El problema es que no se donde meter la linea de:

[AFJSONRequestOperation addAcceptableContentTypes:[NSSet setWithObject:@"application/json-rpc"]];

Y tampoco se si me va a funcionar porque no entiendo muy bien que significa lo de "application/json-rpc"

0voto

juancruzmdq comentado

no, no te va a solucionar el problema.
El mensaje de error te dice que tu aplicacion esta esperando una respuesta de alguno de estos tipos "text/json", "application/json", "text/javascript". pero tu API esta respondiendo con informacion de este tipo "text/html". Estos valores son parte de los header de la request y del response
http://en.wikipedia.org/wiki/List_of_HTTP_header_fields

Tenes dos soluciones
1) en tu API cuando setear el content type de la respuesta al tipo que corresponde ( text/json )
http://php.net/manual/en/function.header.php

2) En tu app especificar que text/html es un tipo aceptado.
[AFJSONRequestOperation addAcceptableContentTypes:[NSSet setWithObject:@"text/html"]];

la solución correcta seria la #1

Otra cosa. me parece que las preguntas se están alejando del tema original. Me pareces que tendrías que crear una pregunta nueva, con las dudas que tengas sobre AFNetworking

0voto

victor_capilla comentado

Para alguien que tenga el mismo problema que yo, le sera incomodo llegar a esta punto y tener que buscar otra pregunta, a parte de que no se a solucionado mi problema.

Te agradezco enormemente todas tus respuestas, te mereces un monumento la verdad.

Muchas gracias, realizare la prueba y zanjare el tema en cuanto lo pruebe.

0voto

Peter comentado

Si llegas a la solución, por favor la publicas :)

0voto

victor_capilla comentado

Ahora mismo he llegado al punto en el que recupero los datos del JSON pero no se como tratarlos. Si yo ago un NSLog(@"%@",JSON) me retorna esto:

 { code = 22051310;
    },
        {
        code = 22051311;
    },
        {
        code = 22051312;
    },
        {
        code = 22051313;
}

El problema ahora es que no se como meterlo en un Array o en un Diccionario. Pero como dice el compañero Juan Cruz, posiblemente tendre que abrir otro hilo para seguir con esto otro...

0voto

juancruzmdq comentado

barbaro,
para parsear el json en un diccionario te habia pasado el codigo en otra respuesta

-(NSDictionary *)dictionaryFromJson:(NSString *) JSONString
{
JSONDecoder * decoder = [[JSONDecoder alloc] initWithParseOptions:JKParseOptionNone];
return [decoder mutableObjectWithData:[JSONString JSONData]];
}

acordate de incluir JSONKIT

#import <JSONKit/JSONKit.h>

0voto

victor_capilla comentado

Te cuento. La cosa ya esta solucionada lo que he tenido que cambiar el tipo de datos que devuelve el metido, en vez de dictionary que sea Array y así me a funcionado todo al a perfección! Muchísimas gracias a todos por vuestra ayuda. Si necesitáis que especifique algo mas ya me diréis!

0voto

juancruzmdq comentado

que bueno que funciono. si la respuesta te sirvio tendrias que marcarla como correcta.
Saludos

0voto

victor_capilla comentado

Tengo u nuevo problema relacionado con esto, es a la hora de enviar datos para que se guarden. Puedo comentarlo aquí o es mejor crear un hilo nuevo?

0voto

juancruzmdq comentado

Yo probablemete crearia un hilo nuevo, pero si queres preguntarla aca no hay problema

0voto

victor_capilla comentado

Como gestiono un JSON vacío, es decir, si la select que realizo en el webservice no devuelve ningún valor?

0voto

juancruzmdq comentado

Creo que depende a que te refieras con vacio.
Si logeas JSON, que te muestra?
NSLog(@"JSON VALUE : %@",JSON)

Es nil? o un array vacío?

0voto

victor_capilla comentado

No llega ni a ejecutarme esa linea, me devuelve directamente este error en el log

The operation couldn’t be completed. (Cocoa error 3840.)JSON text did
not start with array or object and option to allow fragments not set.

Lo que he encontrado por Google son porque no han puesto bien los datos dentro del JSON, no he encontrado ninguno que diga que esta vacío y como controlarlo.

0voto

juancruzmdq comentado

la API no esta respondiendo con un JSON valido.

proba de setear esta opcion en la operacion antes de ejecutarla

operation.JSONReadingOptions = NSJSONReadingAllowFragments;
[operation start];

esto va a permitir que acepte la respuesta de la api aunque no sea ni un array ni un diccionario valido.
volve a loguear JSON para ver que te devuelve la API

0voto

juancruzmdq comentado

perdon, no es que no recibe un JSON valido, es que no recibe ni un array ni un diccionario json valido

0voto

Peter comentado

Por favor crea una pregunta nueva. Es relacionada, pero no es lo mismo.

0voto

victor_capilla comentado

Perfecto, allá voy!

1voto

juancruzmdq Puntos1500

Enviar GET/POST con parametros

//Aca hay un post con un ejemplo simple
http://samwize.com/2012/10/25/simple-get-post-afnetworking/

//fijate que en el ejemplo del POST setea este encoding para los parametros que envía

[httpClient setParameterEncoding:AFJSONParameterEncoding];

// Con esto podes crear un diccionario con el string del JSON que te devuelve la llamada (usa JSONKIT)

-(NSDictionary *)dictionaryFromJson:(NSString *) JSONString
{
JSONDecoder * decoder = [[JSONDecoder alloc] initWithParseOptions:JKParseOptionNone];
return [decoder mutableObjectWithData:[JSONString JSONData]];
}

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta