(Réglé) Un problème de block
Hello à tous,
Une fois sur deux j'ai cette erreur dans mon application
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 12 beyond bounds [0 .. 11]'
*** First throw call stack:
(0x2e1d8fd3 0x38a51ccf 0x2e10f81b 0xabc15 0xadec7 0x2ebedf35 0x2eb1c3c7 0x2eb0c5ab 0x2ebb076d 0x38f3981f 0x38f4049f 0x2e1a38f1 0x2e1a21c5 0x2e10cf0f 0x2e10ccf3 0x33065663 0x30a5816d 0xd3049 0x38f5eab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
J'ai bien compris qu'il ne trouvais pas d'index 12 mais ça me parait bizarre puisqu'il existe bel et bien
Le code est le suivant:
[self getImageOfId:[_offreDetail objectAtIndex:9] completion:^(NSArray *imgArray, BOOL success) {
[_offreDetail addObject:imgArray];//12
for (int cptImg = 0; cptImg<[[_offreDetail objectAtIndex:12]count];cptImg++)
{
if(cptImg<5)
{
if([[_offreDetail objectAtIndex:12]objectAtIndex:cptImg])
{
NSString* imgLink=[[_offreDetail objectAtIndex:12]objectAtIndex:cptImg];
NSString* lienImg = [NSString stringWithFormat:@%@%@",_baseURL,imgLink];
NSURL* urlImg = [NSURL URLWithString:[lienImg stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
if(cptImg==0)
{
_image1.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:urlImg]];
}
else if(cptImg==1)
{
_image2.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:urlImg]];
}
else if(cptImg==2)
{
_image3.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:urlImg]];
}
else if(cptImg==3)
{
_image4.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:urlImg]];
}
else
{
_image5.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:urlImg]];
}
}
}
}
}];
-(void)getImageOfId:(NSObject*) entier completion:(void(^)(NSArray *array, BOOL success))completion
{
NSURL *link = [NSURL URLWithString:[NSString stringWithFormat:@%@", @http://www.pwipwi.com/azazaz/modeles/android/getImagesOffers.php]];
NSMutableURLRequest *URLrequest = [NSMutableURLRequest requestWithURL:link];
NSString *post = [NSString stringWithFormat:@id=%@",entier];
post = [post stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *dataRequest = [post dataUsingEncoding:NSUTF8StringEncoding];
URLrequest.HTTPBody = dataRequest;
URLrequest.HTTPMethod = @POST;
[NSURLConnection sendAsynchronousRequest:URLrequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (data != nil && !connectionError)
{
id stringResult=nil;
int cmpt;
NSError* error1;
stringResult = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error1];
_tabImg = [[NSMutableArray alloc]init];
for(cmpt=0; cmpt<[stringResult count];cmpt++)
{
NSDictionary *tempDic = [stringResult objectAtIndex:cmpt];
[_tabImg addObject:[tempDic objectForKey:@nom]];
}
completion(_tabImg, YES);
}
else {
completion(nil, NO);
NSLog(@Error = %@", connectionError);
}
}];
}
Merci d'avance à ceux qui m'aideront
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Le message est clair... L'index 12 n'existe pas... Comme tu as l'air de le supposer (titre "problème de block"), l'utilisation de l'index 12 doit se faire trop tôt (afin la fin de ton code asynchrone). D'ailleurs, c'est pour çà que tu l'as une fois de temps en temps cette erreur. Il doit arriver que la réponse doit se faire plus vite dans certains cas.
Euh, et c'est quoi ce magic number (12) au milieu du code ?!! xd
Edit : d'ailleurs, il y en a d'autres des magic numbers... C'est généralement déconseillé.
Salut,
Merci pour ta réponse
En fait mon tableau _offreDetail contient déjà 11 valeurs, pour ça que quand je fais un addObject je sais que l'objet s'ajoute à l'index 12.
L'index 12 de mon tableau est censé me renvoyer un tableau d'images, parfois il me le renvoie correctement sans aucun souci, d'autres fois il me pète à la gueule et me crash l'application, alors je comprends pas vraiment la logique à vrai dire, pourquoi parfois ça marche alors que d'autres fois non ?
J'ai pas compris ce que tu voulais dire
Il me semble qu'ajouter un nil dans un tableau créer un crash de l'application ce qui veut dire que potentiellement ton application plantera de temps à autre vu ton code mais c'est encore un autre souci.
As tu au moins loggé ton array pour voir si cet index 12 existe réellement?
As tu pensé à changer la conception de ce sac de noeud pour que cela devienne plus simple et donc compréhensible?
Pour l'instant ce que j'imagine c'est que tu fais pas mal de bloc dans ce genre là à la suite ce qui te remplis ton _offreDetail au fur et à mesure (c'est ce que j'imagine parce que je t'avoues que je vois pas bien comment ça pourrait marcher autrement.) et du coup comme tu fais un add si jamais un des traitement en amont ne fonctionne pas il se peut que ton array d'image ne soit pas à l'index 12 comme tu le souhaite mais à l'index 10 ou 11 (puisque l'index 9 est potentiellement déjà occuper pendant l'appel du bloc)
Voila de quoi on parlait hier quand on te disait que ce genre de code mène à des erreurs aléatoire et à des compréhension très relative des problème.
Ici par exemple à tout stocker dans une liste je ferais ça dans un dictionnaire au moins pas de souci d'ordre et tu appels ton résultat avec une clé et non pas un index ordonné.
Quand tu fais ça :
Si tu rajoutes ça :
T'as quoi ?
Apparemment, t'as un BOOL success, t'as regardé sa valeur avant de faire quoi que ce soit ? Car s'il est à FALSE, imageArray pourrait poser problème.
@Larme: Cas ou tout va bien:
success vaut 1
_offreDetail count vaut 12
Cas ou ça plante:
success vaut 1
_offreDetail count vaut 11
@Nasa: Pour ce code, je me suis basé sur ce que tu m'avais envoyé par MP et je l'ai adapté à la situation. En réalité je fais "seulement" 2 fois un bloc de ce type, 1 fois pour l'index 11 (les options), et une autre fois pour le 12 (lié aux images).
Quand je fais un log de mon tableau il s'avère que bizarrement il ne m'affiche pas l'index 11 (les options) qui est lui aussi un block quand cela plante.
Voila le code pour l'objet à l'index 11 (les options)
Dans cette méthode success vaut toujours 1
Moi je t'ai envoyé la structure d'un block la structure du block est pas si mal c'est plutôt le reste qui pose problème. Enfin de ce que je vois après je suis pas sur de saisir ce que ça doit faire tout ça.
En fait dans mes blocks, je doit ajouter plusieurs valeurs dans un tableau (d'options ou d'images, selon le cas), qui sera lui même ajouté à mon tableau _offreDetail
Et voila c'est bien ce qu'on te dit c'est un problème de concurrence si ta fonction index 11 met plus de temps à s'executer que ta fonction index 12 ben ton index 12 est à la place de ton index 11 et donc pas à l'index 12 de la à dire que c'est ma structure de block qui est en cause je trouve ça un peu gros. (et la en lisant ma phrase tu devrais te dire c'est compliquer à comprendre peut être que si j'arrivais à simplifier mon système je simplifierais le problème et la solution apparaitrait d'elle même).
Donc je te renvoies à mon premier message et à celui de Larme qui t'explique comment régler ton problème (ce qui n'est pas si compliqué).
Le message de Larme, j'ai suivi ce qu'il m'a dit à la lettre, et cela sans résultat.
Et je suis en train de passer de tableau à dictionnaire en espérant que cela règle le souci
Ben si tu as eu un résultat tu vois que ton index n'existe pas si tu lis ce que tu fais tu vois bien que tu es en train d'empiler des résultat dans une liste tu lances tes actions dans le genre
Action 1 -> ajoute un index 11
Action 2 -> ajoute un index 12
donc dans ton code si tu fait
Action 1 -> En attente
Action 2 -> ajoute un index 11
Puis plus tard
Action 1 -> ajoute surement un index 12
C'est peut être que ton Action 1 rajoutera plus tard un index 12 enfin moi je dis ça je connais pas plus le code que ça.
Donc ce qu'on te dit depuis le début c'est de te dédouaner des système d'index car tu ne saura jamais dans quel ordre seront exécutés tes méthodes car elles sont asynchrones.
Donc Larme ne t'a pas donné une solution ce que tu attends manifestement mais un axe de réflexion pour que tu puisse comprendre ce qui arrive et que dans un future plus ou moins proche si tu croise de nouveau se problème tu puisse le régler tout seul.
Non mais Larme m'a dit qu'il n'y avais pas d'index 12, hors ça je le savais dès le départ vu que c'est pour cela que l'appli me faisait un crash.
Bref je met mes données dans un dictionnaire on verras si ça va mieux
Sinon, plutôt que de hardcoder le magicnumber "12", tu pourrais pas le remplacer par [_offreDetail count] -1 ?
Sinon, vu que ce sont deux blocks, je ne ferais le traitement qu'une fois que le block a réellement terminé...
Ben as tu compris au moins le problème avec le success? Si tu as pas compris ça ton application plantera tôt ou tard c'est impossible autrement ça paraitra pour un bug aléatoire très compliqué à reproduire.
@Larme est ce que tu penses que le cas que "j'essais" de décrire pourrait arriver? Je suis pas allé assez loin dans la consommation des blocks pour savoir ça.
Je penses que son code donne ça :
uneFonction{
block1 [devra remplir l'index 10];
block2 [devra remplir l'index 11];
block3 [devra remplir l'index 12];
}
Alors c'est la que je suis pas trop sur de moi c'est vrais que ça peut paraitre tordue mais moi j'aurais peur que deux block se termine simultanément (ou très presque) et qu'il y ai quand même un souci d'index (ça limiterai les cas c'est sur mais ça laisserait des chances non?).
Oui j'ai compris le problème du sucess, faut que je fasse un if success = 1, car si c'est false forcément ça va me faire une erreur.
Concernant mes blocks non ça fait
Sinon je suis en train de voir pour transformer mon tableau en dictionnaire,
J'ai donc fait ça
au lieu de ça
Je doit maintenant transformer ce truc
en quelque chose comme cela
mais avec un index (indexPath.row) seulement je vois pas ou mettre l'index :S
Houla... Ok on pause le clavier et on réfléchi.
Ton dictionnaire pour moi doit juste remplacer ton _offreDetail
Du coup tu aura
J'en ai peut être oublié. Je sais pas ce que tu veux faire mais pour moi sans changer tout ton code ça reste le plus simple et le plus sur.
Je veut bien qu'on fasse ça pour la phase de détail de l'offre,
Mais si je doit mettre en place un dictionnaire à la place d'un tableau je doit le faire dès ma liste d'offre, car c'est à ce moment la que je crée mon tableau de 11 éléments, et seulement dans le détail je rajoute les 2 derniers éléments
Avant je faisais ça:
for(cpt=0; cpt<[strResult count];cpt++)
Puis ensuite un:
dans mon - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
No visible @interface for 'NSMutableDictionary' declares the selector 'setObject:atIndex:'
Par contre iL y a bien un
Utilise ça plutot:
voir:
Ce code ne marche pas et ne m'affiche pas mes images
Ah ouais le revers du copier coller...
Avec autant d'information c'est trop facile tu devrais juste donner la première partie là on sait que ça parle d'image.
Oui en fait je vais juste faire ça pour les options et les images
Avec ça j'ai aucune image qui s'affiche...
Aucun rapport avec ton problème, mais quand je vois tes 5 if/else, je me demande s'il ne serait pas plus intéressant de les mettre dans un NSArray et de faire ainsi :
As tu initialisé ton _dicoDetail?
Je suis pas un grand fan de l'écriture que tu utiliser mais j'imagine que
_dicoDetail[@monIndex] = imgArray;
équivaut à :
[_dicoDetail setObject:imageArray forKey:@monIndex];
Du coup si ton dictionnaire est nul ça ne marche pas.
Mais bon comme tout bon débugger j'imagine aussi que tu as loggé ton _dicoDetail et que donc tu sais ce qu'il contient. Du coup je vois pas trop d'où ça vient.
Enfin après ça c'est que pour rendre le code moins lourd à lire ça te donnera le même résultat.