web-dev-qa-db-fra.com

comment utiliser sendAsynchronousRequest: queue: completionHandler:

Question en deux parties

Première partie: J'essaie de créer une requête ASynchrone dans ma base de données. Je le fais actuellement de manière synchrone, mais je veux apprendre les deux façons d'améliorer ma compréhension de ce qui se passe.

Actuellement, j'ai configuré mon appel synchrone comme ceci.

- (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);
    }
}

Je pense que ce que je dois faire est de remplacer l'appel

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

avec la version ASynchrone

sendAsynchronousRequest:queue:completionHandler:

cependant, je ne suis pas sûr de ce qu'il faut transmettre à la file d'attente ou d'achèvementHandler ... Tous les exemples/solutions seraient grandement appréciés.

Deuxième partie: Je lisais sur le multitâche et je voudrais le soutenir en veillant à ce que mes demandes de connexion soient complètes s'il y a une interruption. J'ai suivi cette exemple

Dans ce document, il explique comment gagner plus de temps si une interruption se produit, je comprends ce qu’il fait. Mais comment l’appliquer à cette connexion? Si vous avez des exemples/tutoriels pour m'aider à comprendre comment l'appliquer, ce serait génial!

74
C.Johns

Partie 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
mbh

Voici un échantillon:

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
Flea

Pour le paramètre queue, essayez cette magie:

[NSOperationQueue mainQueue]

Cela fonctionne très bien si vous mettez à jour l'interface utilisateur à la fin de la demande car la file d'attente principale est le fil principal. Cela vous indique essentiellement le comportement précédent de NSURLConnection. Si, toutefois, vous envisagez d'écrire dans un fichier ou de décompresser, vous pouvez terminer dans une file d'attente en arrière-plan, puis renvoyer asynchrone vers la file principale pour les mises à jour de l'interface utilisateur.

26
malhal

J'ai travaillé sur un problème similaire, j'ai posté cette question et obtenu une réponse claire ici , j'espère que cela aidera avec la partie 2.

Pour la partie 1 ce que les autres mentionnés ici sont bons mais vous devez ajouter un autre chèque (j'ai modifié une réponse ci-dessous). Il est possible que votre demande renvoie une erreur 404 (page non trouvée), auquel cas vous n'obtiendrez pas d'erreur et les données seront> 0. Le 200 est une bonne réponse, vous pouvez également vérifier le code d'état pour 404 ou autre. .

     [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
Recycled Steel

Puisque sendAsynchronousRequest:urlRequest queue:queue completionHandler: est obsolète dans iOS 9 et il sera suggéré d'utiliser NSURLSession's -dataTaskWithRequest:completionHandler: à la place. Il est disponible depuis iOS 7 et versions ultérieures .

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) {
     // ...
 }];

Par 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];
4
AechoLiu

sendAsynchronousRequest est obsolète dans Swift. Déplacer vers dataTaskWithRequest, heureusement, il est utilisé à peu près de la même manière.

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
Bhavesh Patel