2014-06-16 2 views
1

J'ai créé un customDownload de classe avec les méthodes suivantes:Connexion Asynchronous Télécharger Callback

-(NSString *) getTextFromLink: (PreliteRequest *) requestDetails 
       asyncConnection: (BOOL) isAsync 
       callbackMethod: (SEL) methodToExecute { 

    mainRequest = requestDetails; 

    NSMutableURLRequest *postRequest = [[NSMutableURLRequest alloc] init]; 
    NSURLRequest *getRequest = [[NSURLRequest alloc] init]; 
    NSURLConnection *connection; 

    NSURLResponse * response = nil; 
    NSError * error = nil; 

    if ([[requestDetails getType] isEqualToString:@"POST"]) { 
     [postRequest setURL:[NSURL URLWithString:[requestDetails getUrl]]]; 
     [postRequest setHTTPMethod:[requestDetails getType]]; 
     [postRequest setValue:[requestDetails getPostLenght] forHTTPHeaderField:@"Content-Length"]; 
     [postRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 
     [postRequest setHTTPBody:[requestDetails getPostParameters]]; 

     if (isAsync) { 
      tmpMethod = methodToExecute; 
      connection = [[NSURLConnection alloc] initWithRequest:postRequest delegate:self]; 
     } else 
      downloadedData = (NSMutableData *)[NSURLConnection sendSynchronousRequest:postRequest returningResponse:&response error:&error]; 
    } else { 
     getRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@",[requestDetails getUrl],[requestDetails getGetParameters]]]]; 
     if (isAsync) { 
      tmpMethod = methodToExecute; 
      connection = [[NSURLConnection alloc] initWithRequest:getRequest delegate:self]; 
     } else 
      downloadedData = (NSMutableData *)[NSURLConnection sendSynchronousRequest:getRequest returningResponse:&response error:&error]; 
    } 

    NSString *result=[[NSString alloc]initWithData:downloadedData encoding:NSUTF8StringEncoding]; 

    return result; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 
    downloadedData = [[NSMutableData alloc] init]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    // Append the new data to the instance variable you declared 
    [downloadedData appendData:data]; 
} 

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection 
        willCacheResponse:(NSCachedURLResponse*)cachedResponse { 


    return nil; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 

    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 

    NSString *tmpResult = [[NSString alloc]initWithData:downloadedData encoding:NSUTF8StringEncoding]; 

    [self performSelector:tmpMethod withObject:tmpResult]; 

} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 
    NSLog(@"Connection error: %@",error); 
} 

Dans mon contrôleur de vue, je déclare la classe précédente et appelle la seule méthode de cette classe getTextFromLink.

download = [[customDownload alloc] init]; 
[download getTextFromLink:request asyncConnection:YES callbackMethod:tmpSelector]; 
SEL tmpSelector = @selector(printResult:); 
-(void) printResult:(NSString *) resultToPrint { 
    NSLog(@"Risultato: %@",resultToPrint); 
} 

Je passe à getTextFromLink le tmpSelector en tant que paramètre parce que c'est la méthode que je voudrais appeler dès le getTextFromDownloadLink a terminé son travail. En fait, getTextFromLink exécute une connexion asynchrone.

Ce que j'essaye de faire est d'exécuter quelque chose quand la connexion asynchrone a fini de télécharger des données. Je voudrais créer une classe personnalisée de rappel pour ce faire.

Quelqu'un peut-il m'aider?

+0

à votre question non reliés à la main, mais je vous suggère de changer que 'PreliteRequest' pour éliminer ces méthodes 'getType',' getUrl', etc., et juste le définir pour avoir les propriétés 'type',' url' et utiliser les getters standards pour cela. – Rob

Répondre

2

Plutôt que ce modèle de sélecteur, généralement les gens utiliseraient des blocs pour cela. Par exemple, définir un typedef pour votre bloc:

typedef void(^PreliteRequestCompletionHandler)(NSString *string); 

Puisque vous avez affaire à un modèle asynchrone, vous pouvez définir une propriété que vous pouvez utiliser pour enregistrer ce gestionnaire d'achèvement pour appeler plus tard:

@property (nonatomic, copy) PreliteRequestCompletionHandler completionHandler; 

vous pouvez ensuite modifier ce paramètre de sélection pour être un paramètre de bloc:

-(NSString *) getTextFromLink: (PreliteRequest *) requestDetails 
       asyncConnection: (BOOL) isAsync 
      completionHandler: (PreliteRequestCompletionHandler)completionHandler { 

    self.completionHandler = completionHandler; 

    // do stuff 
} 

Et puis, quand vous voulez appeler ce bloc d'achèvement, vous d o quelque chose comme:

NSString *result = ...; 

if (self.completionHandler) { 
    self.completionHandler(result); 
} 

Et vous pouvez maintenant utiliser ce nouveau paramètre de bloc à votre méthode:

download = [[customDownload alloc] init]; 
[download getTextFromLink:request asyncConnection:YES completionHandler:^(NSString *result) { 
    NSLog(@"Risultato: %@", result); 
}]; 
+0

@prelite BTW, j'ai utilisé un seul 'NSString *' pour le paramètre au gestionnaire de complétion parce que c'est ce que votre exemple utilisait, mais vous pourriez vouloir deux paramètres, un 'NSString' en cas de succès, et un' NSError' sinon (this est le modèle que Cocoa utilise généralement). Vous pouvez également utiliser un bloc de gestionnaire d'échec distinct (qui est un modèle utilisé par AFNetworking). L'une ou l'autre fonctionne, mais de toute façon, vous voulez que votre code qui appelle 'getTextFromLink' soit capable de détecter et de gérer les erreurs. – Rob

+0

Merci beaucoup Rob ... Il wokerd parfaitement ... Depuis maintenant je ne savais pas quels blocs vous étiez juste ouvert un nouveau monde à moi ... merci encore ... – prelite

+0

Rob, pouvez-vous expliquer pourquoi vous avez le qualificatif "copy" pour votre PreliteRequestCompletionHandler. J'étais sur le point de poster une réponse similaire quand j'ai vu le vôtre. Je n'ai pas utilisé de copie, et cela a semblé fonctionner correctement. – rdelmar