Requête synchrone vers asynchrone
Bonjour,
Oui je sais que je suis chiant, que j'ai déjà posé 10 questions sur l'asynchronisme, mais la je bloque pour transformer ma requête synchrone en asynchrone afin d'optimiser mon app et que ça ne soit plus aussi long (car la actuellement on voit cette vue Connexion 5 secondes, avant que ça passe sur la suivante Profil)
- (NSData *)executePostCall {
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@%@", @http://monsite.com/azazaz/modeles/android/login.php]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@MonApp accessGroup:nil];
NSString *adEmail = [keychainItem objectForKey:(__bridge id)(kSecValueData)];
NSString *pwd = [keychainItem objectForKey:(__bridge id)(kSecAttrAccount)];
MyManager *sharedManager = [MyManager sharedManager];
NSString *requestFields = @"";
if(![_email.text isEqualToString:@""] && ![_password.text isEqualToString:@""])
{
requestFields = [requestFields stringByAppendingFormat:@email=%@&", _email.text];
requestFields = [requestFields stringByAppendingFormat:@password=%@", [self md5:_password.text]];
}
else if(![adEmail isEqualToString:@""] && ![pwd isEqualToString:@""])
{
requestFields = [requestFields stringByAppendingFormat:@email=%@&", adEmail];
requestFields = [requestFields stringByAppendingFormat:@password=%@", pwd];
}
else if(sharedManager.userName !=nil)
{
requestFields = [requestFields stringByAppendingFormat:@email=%@&", sharedManager.userName];
requestFields = [requestFields stringByAppendingFormat:@password=%@", sharedManager.pass];
}
requestFields = [requestFields stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *requestData = [requestFields dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = requestData;
request.HTTPMethod = @POST;
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error == nil && response.statusCode == 200) {
} else {
}
return responseData;
}
Je l'utilise comme cela par la suite:
- (void)viewDidLoad
{
[super viewDidLoad];
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@MonApp accessGroup:nil];
NSString *adEmail = [keychainItem objectForKey:(__bridge id)(kSecValueData)];
NSString *pwd = [keychainItem objectForKey:(__bridge id)(kSecAttrAccount)];
if(![adEmail isEqualToString:@""] && ![pwd isEqualToString:@""])
{
dispatch_queue_t downloadQueue = dispatch_queue_create("downloader", NULL);
dispatch_async(downloadQueue, ^{
NSData *result = [self executePostCall];
dispatch_async(dispatch_get_main_queue(), ^{
id strResult=nil;
strResult = [NSJSONSerialization JSONObjectWithData:result options:0 error:nil];
NSString* boolOk=[strResult objectForKey:@result];
if([boolOk isEqualToString:@ok])
{
Profil* prof=[[Profil alloc]init];
prof.email=adEmail;
prof.password=pwd;
[self.navigationController pushViewController:prof animated:NO];
[prof getMemberInfo];
[prof getUserOffers];
}
});
});
}
MyManager *sharedManager = [MyManager sharedManager];
if(sharedManager.userName !=nil)
{
dispatch_queue_t downloadQueue = dispatch_queue_create("downloader", NULL);
dispatch_async(downloadQueue, ^{
NSData *result = [self executePostCall];
dispatch_async(dispatch_get_main_queue(), ^{
id strResult=nil;
strResult = [NSJSONSerialization JSONObjectWithData:result options:0 error:nil];
NSString* boolOk=[strResult objectForKey:@result];
if([boolOk isEqualToString:@ok])
{
Profil* prof=[[Profil alloc]init];
prof.email=sharedManager.userName;
prof.password=sharedManager.pass;
[self.navigationController pushViewController:prof animated:NO];
[prof getMemberInfo];
[prof getUserOffers];
}
});
});
}
}
Merci d'avance à ceux qui m'aideront
Mots clés:
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Hello,
Utilise plutôt les méthodes asynchrones de NSURLConnection.
http://forum.cocoacafe.fr/topic/12678-réglé-sérialisation-très-longue/page-2
@Aligator
C'est justement ce que je cherche à faire (d'où le titre), seulement je vois pas trop comment l'adapter, vu que ma seule valeur de retour c'est une data représentant ma requête synchrone
Utilises un block pour ta méthode executePostCall, tu appeles ton block à la fin de la requête asynchrone.
Construis le block avec les bons paramètres ( NSData et NSError peut être ).
( d'ailleurs il faut donner un autre nom de méthode à executePostCall ).
@Ben77650
??? Tu veux vraiment que ça soit plus long? ou que ça ne soit plus long ... donc plus court?
@tablier, je me suis mal exprimé, que ce ne soit plus aussi long, (donc plus court)
@Ali @Samir
Quelque chose comme cela ?
Je changerais le nom de la méthode par la suite
Bonjour,
Oui ça à a l'air correct ton choix de remplissage de mail / mot de passe me parait un peu bancale dans le sens ou même si on sait que le couple n'est pas remplie on envoie quand meme la requête qui renverra un "NO" à chaque fois mais bon c'est plus ou moins ce que tu attends ça fait juste une requête pour rien.
Sinon y a ce genre de ligne qui pour moi devrait renvoyer un warning
Les deux lignes sont équivalentes elles te retourneront toutes les deux une url valide par contre je penses que ta façon de faire est plus gourmande car le compilateur va chercher à faire une concaténation de chaine de caractère pour rien.
Pour finir peut être qu'en plus de la verification sur le "error" je ferais un retour du serveur ne serait ce que pour renvoyer un message adapté que l'on pourrait affiché à l'utilisateur "login/mdp incorrect", "Compte bannis" ou "Compte déjà loggé ailleurs" je dis pas que tu devras mettre ces messages mais il peut éventuellement être pratique des les avoir.
De plus je ne suis pas sur qu'un fail de connexion renvoies une erreur et du coup avec cette méthode je penses que tout le monde sera connecté du coté applicatif même si évidemment le serveur considérera lui que les code sont non valide et ne reverra pas de données. (à tester car suivant comment tu fais ta connexion il renverra surement une erreur http du style error 401 unauthorized)
Hello,
Tu es sur la bonne voie .
Y a deux problème avec ta solution :
1. Il faut jamais tester le retour de ta méthode sur l'objet error. Si tu regarde la documentation de la méthode sendAsynchro...
tu verra que si le data est nil dans ce cas la requête à échouée et c'est la qu'il faut regarder le détail de l'erreur dans l'objet error, et si il est différent de nil la requête à réussi.
2. Tu ne récupère pas les données retournées par ta requête réseaux ( data), puisque tu as juste défini ton block avec un seul paramètre ( Bool) donc tu vas juste savoir si la requête a réussi ou pas. Si tu veux récupérer les données aussi ( peut être l'erreur aussi) il faut rajouter un autre paramètre à ton block ( un NSData par exemple).