cómo usar sendAsynchronousRequest: queue: completionHandler:


Pregunta en dos partes

Primera parte: Estoy tratando de crear una solicitud asincrónica a mi base de datos. Actualmente lo estoy haciendo Sincrónicamente, sin embargo, quiero aprender ambas formas para mejorar mi comprensión de lo que está pasando.

Actualmente he configurado mi llamada síncrona de esta manera.

- (IBAction)setRequestString:(NSString *)string
{
    //Set database address
    NSMutableString *databaseURL = [[NSMutableString alloc] initWithString:@"http://127.0.0.1:8778/instacodeData/"]; // imac development

    //PHP file name is being set from the parent view
    [databaseURL appendString:string];

    //call ASIHTTP delegates (Used to connect to database)
    NSURL *url = [NSURL URLWithString:databaseURL];

    //SynchronousRequest to grab the data
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSError *error;
    NSURLResponse *response;

    NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
    if (!result) {
        //Display error message here
        NSLog(@"Error");
    } else {

        //TODO: set up stuff that needs to work on the data here.
        NSString* newStr = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
        NSLog(@"%@", newStr);
    }
}

Creo que lo que tengo que hacer es reemplazar la llamada

NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

Con la versión asíncrona

sendAsynchronousRequest:queue:completionHandler:

Sin embargo, no estoy seguro de qué pasar a la cola o completionHandler... Cualquier ejemplo / solución sería muy apreciada.

Segunda parte: He estado leyendo sobre multitarea y me gustaría apoyarlo asegurándome de que mis solicitudes de conexión se completen si hay una interrupción. He estado siguiendo este ejemplo

En él se explica cómo ganar más tiempo si se produce una interrupción, entiendo lo que está haciendo.. ¿pero no cómo aplicarlo a esta conexión? si tienes algún ejemplo / tutorial que me ayude averiguar cómo aplicarlo que sería impresionante!

Author: C.Johns, 2012-02-14

6 answers

Parte 1:

NSURL *url = [NSURL URLWithString:urlString];

NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
    if ([data length] > 0 && error == nil)
        [delegate receivedData:data];
    else if ([data length] == 0 && error == nil)
        [delegate emptyReply];
    else if (error != nil && error.code == ERROR_CODE_TIMEOUT)
        [delegate timedOut];
    else if (error != nil)
        [delegate downloadError:error];
}];
 114
Author: mbh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-14 01:58:24

Aquí hay una muestra:

NSString *urlAsString = @"http://www.cnn.com";
NSURL *url = [NSURL URLWithString:urlAsString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];


[NSURLConnection
         sendAsynchronousRequest:urlRequest
         queue:[[NSOperationQueue alloc] init]
         completionHandler:^(NSURLResponse *response,
                             NSData *data,
                             NSError *error) 
        {

         if ([data length] >0 && error == nil)
         {

                        // DO YOUR WORK HERE

         }
         else if ([data length] == 0 && error == nil)
         {
             NSLog(@"Nothing was downloaded.");
         }
         else if (error != nil){
             NSLog(@"Error = %@", error);
         }

     }];
 38
Author: Flea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-18 16:42:44

Para el parámetro de cola, prueba esta magia:

[NSOperationQueue mainQueue]

Esto funciona muy bien si está actualizando la interfaz de usuario al completar la solicitud, ya que la cola principal es el hilo principal. Esencialmente le da el comportamiento anterior de NSURLConnection. Sin embargo, si planea escribir en archivo o descomprimir, puede completar en una cola en segundo plano y luego enviar async a la cola principal para las actualizaciones de la interfaz de usuario.

 26
Author: malhal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-10 19:10:04

He estado trabajando en un problema similar, publiqué esta pregunta y obtuve una respuesta clara aquí, espero que eso ayude con la Parte 2.

Para la parte 1 lo que los otros mencionados aquí son buenos, pero necesita agregar otra verificación (he modificado una respuesta a continuación). Es posible que su solicitud devolverá digamos un Error 404 (página no encontrada) en cuyo caso no obtendrá y el error y los datos serán > 0. El 200 es una buena respuesta, también puede comprobar el código de estado para 404 o Lo que sea.

     [NSURLConnection
     sendAsynchronousRequest:urlRequest
     queue:[[NSOperationQueue alloc] init]
     completionHandler:^(NSURLResponse *response,
                         NSData *data,
                         NSError *error) 
    {
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
     if ([data length] >0 && error == nil && [httpResponse statusCode] == 200)
     {

                    // DO YOUR WORK HERE

     }
 9
Author: Recycled Steel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:05

Ya que sendAsynchronousRequest:urlRequest queue:queue completionHandler: ha sido obsoleto en iOS 9, y sugerirá usar NSURLSession's -dataTaskWithRequest:completionHandler: en su lugar. Está disponible desde iOS 7 y posteriores .

Original:

 NSURL *URL = [NSURL URLWithString:@"http://example.com"];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];

 [NSURLConnection sendAsynchronousRequest:request
                                    queue:[NSOperationQueue mainQueue]
                        completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
     // ...
 }];

Por NSURLSession:

 NSURL *URL = [NSURL URLWithString:@"http://example.com"];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];

 NSURLSession *session = [NSURLSession sharedSession];
 NSURLSessionDataTask *task = [session dataTaskWithRequest:request
                                         completionHandler:
     ^(NSData *data, NSURLResponse *response, NSError *error) {
         // ...
     }];

 [task resume];
 3
Author: AechoLiu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-20 06:16:01

sendAsynchronousRequest ha sido obsoleto en Swift. Mover a dataTaskWithRequest, por suerte se utiliza más o menos de la misma manera.

if let url = NSURL(string:"http://your_url") {

    let request:NSURLRequest = NSURLRequest(URL: url)
    let config = NSURLSessionConfiguration.defaultSessionConfiguration()
    let session = NSURLSession(configuration: config)

    let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in

    });

    task.resume()
}
 2
Author: Bhavesh Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-18 05:06:54