Estoy tratando de hacer una clase simple que puedo usar para llamar a un puesto de servicio web.

Todo funciona a la perfección excepto que yo no soy capaz de devolver el NSData.

Este es mi código:

+ (NSData *)postCall:(NSDictionary *)parameters fromURL:(NSString *)url{
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
    NSMutableArray *pairs = [[NSMutableArray alloc]init];
    for(NSString *key in parameters){
        [pairs addObject:[NSString stringWithFormat:@"%@=%@", key, parameters[key]]];
    }
    NSString *requestParameters = [pairs componentsJoinedByString:@"$"];
    NSURL *nsurl = [NSURL URLWithString:url];
    NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:nsurl];
    [urlRequest setHTTPMethod:@"POST"];
    [urlRequest setHTTPBody:[requestParameters dataUsingEncoding:NSUTF8StringEncoding]];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        //return data;
    }];
    [dataTask resume];

    return nil;
}

Por favor, observe que he //return data pero me da este error

 Incompatible block pointer types sending 'NSData *(^)(NSData *__strong, NSURLResponse *__strong, NSError *__strong)' to parameter of type 'void (^)(NSData *__strong, NSURLResponse *__strong, NSError *__strong)'

Mi pregunta es:

  1. Es mi manera buena o me causa problemas en el futuro? No tengo imagen para descargar y no tengo nada para subir, sólo tengo que enviar la cadena sencilla de datos y recibir simpe de datos de cadena. O será mejor, pero ese código en cada una de las funciones de forma independiente?
  2. ¿Cómo puedo devolver los datos por favor?
Por CIERTO, se concatenan su solicitud de parámetros con $. Es que un correcto? Generalmente se recurre a &. Usted también generalmente por ciento escapar de la parameters[key] valor con CFURLCreateStringByAddingPercentEscapes (no stringByAddingPercentEscapesUsingEncoding). Consulte stackoverflow.com/a/23635327/1271826.

OriginalEl autor Carol Smith | 2014-07-20

2 Comentarios

  1. 7

    Usted simplemente no puede devolver los datos (porque el NSURLSessionDataTask se ejecuta de forma asíncrona). Usted probablemente desee emplear su propio perfeccionamiento patrón de bloque, similar a la completionHandler de la dataTaskWithRequest método.

    Así, habría que agregar su propio bloque de parámetro a través de su método, que invocaremos desde el interior de la dataTaskWithRequest del método completionHandler:

    + (NSURLSessionDataTask *)postCall:(NSDictionary *)parameters fromURL:(NSString *)url completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler {
    
        //create your request here ...
    
        NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            if (completionHandler)
                completionHandler(data, response, error);
        }];
    
        [dataTask resume];
    
        return dataTask;
    }

    Nota, creo que es bueno para devolver el NSURLSessionDataTask de referencia, de manera que (a) la persona que llama puede asegurarse de que los datos de la tarea se ha creado correctamente; y (b) usted tiene el NSURLSessionTask de referencia que puede utilizar para cancelar la tarea en caso de que, en el futuro, usted quiere ser capaz de cancelar la solicitud por alguna razón (por ejemplo, el usuario puede ocultar el controlador de vista desde el que se hizo la petición).

    De todos modos, tendría que invocar con esto:

    NSURLSessionTask *task = [MyClass postCall:parameters fromURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        //put whatever code you want to perform when the asynchronous data task completes
    }];
    
    if (!task) {
        //handle failure to create task any way you want
    }

    Pregunta:

    Es mi manera buena o me causa problemas en el futuro? No tengo [un] imagen para descargar y no tengo nada para subir, sólo tengo que enviar [algunos] de cadena simple de datos y recibir [simple] datos de cadena. O será mejor, pero ese código en cada una de las funciones de forma independiente?

    Si usted está recibiendo simple cadena de datos de nuevo, me gustaría sugerir que componen su respuesta en formato JSON, y luego tener la finalización del bloque en postCall uso NSJSONSerialization para extraer la respuesta. El uso de JSON es más fácil para la aplicación de diferenciar entre la respuesta correcta y una variedad de problemas relacionados con el servidor que también podría devolver la cadena de respuestas.

    Así que, digamos que usted modificado su código de servidor para devolver una respuesta así:

    {"response":"some text"}

    Entonces usted podría modificar postCall para analizar la respuesta así:

    + (NSURLSessionDataTask *)postCall:(NSDictionary *)parameters fromURL:(NSString *)url completionHandler:(void (^)(NSString *responseString, NSError *error))completionHandler {
    
        //create your request here ...
    
        NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            if (completionHandler) {
                if (error) {
                    completionHandler(nil, error);
                } else {
                    NSError *parseError = nil;
                    NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
    
                    completionHandler(responseDictionary[@"response"], parseError);
                }
            }
        }];
    
        [dataTask resume];
    
        return dataTask;
    }

    En términos de su pregunta subyacente, si un método como postCall tiene sentido, sí, creo que tiene sentido perfecto para poner los detalles de la creación de la solicitud en un único método. Mi reserva menor en su implementación fue su decisión de hacer de ella un método de clase en lugar de un método de instancia. Actualmente estás creando un nuevo NSURLSession para cada solicitud. Sugeriría hacer postCall un método de instancia (de un singleton si quieres) y, a continuación, guardar la sesión como una propiedad de clase, que se establece de una vez y, a continuación, re-uso en consultas posteriores.

    Muchas gracias por los esfuerzos, pero, por desgracia, no soy capaz de comprobar la respuesta de esta noche ya que estoy un poco ocupado. Sin embargo, voy a comprobarlo mañana. +1 de todos modos.
    Que la edición no era el adecuado: yo estaba citando a la pregunta original, y que ha editado el texto de una cita directa de tal manera que ya no es la misma cita. Creo que los lectores podrán entender lo que está pasando (como las ediciones no eran material), pero yo no aconsejaría edición de algo que es una cita directa del texto original. O si usted edición de la cita, hacerlo explícito, como he hecho anteriormente.
    y he corregido los errores en el original.
    No me refiero a hacer una montaña de un grano de arena, pero, no, no lo hacen de la misma edición en la pregunta original (o si lo hizo, que fueron rechazadas). Se hicieron otras ediciones, pero no es lo mismo que hizo en mi cita directa de la pregunta.
    Gracias Rob. Me estaba arreglando una gran cantidad de errores en los puestos de ayer con la terrible gramática, no estándar de formato de código y debo haber visto simplemente errores y fija. En otros posts, quiero que vuelva y se fija el cartel original de las faltas de ortografía y debe haber perdido el de este hilo.

    OriginalEl autor

  2. 1

    Usted debe usar un método de bloqueo.

    Primero definir un bloque

    typedef void (^OnComplete) (NSData *data);

    Utilice el método siguiente

    + (void)postCall:(NSDictionary *)parameters fromURL:(NSString *)url withBlock:(OnComplete)block; {
    
         NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
            NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
            NSMutableArray *pairs = [[NSMutableArray alloc]init];
            for(NSString *key in parameters){
                [pairs addObject:[NSString stringWithFormat:@"%@=%@", key, parameters[key]]];
            }
            NSString *requestParameters = [pairs componentsJoinedByString:@"$"];
            NSURL *myURL = [NSURL url];
            NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:myURL];
            [urlRequest setHTTPMethod:@"POST"];
            [urlRequest setHTTPBody:[requestParameters dataUsingEncoding:NSUTF8StringEncoding]];
            NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                block(data);
            }];
            [dataTask resume];
       }
    gracias por la edición..
    Aprecio los esfuerzos que muy mucho. Lo siento pero no voy a ser capaz de comprobar que esta noche porque estoy ocupado. Sin embargo, voy a comprobarlo mañana. +1 de todos modos.

    OriginalEl autor

Dejar respuesta

Please enter your comment!
Please enter your name here