2010-03-22 6 views
0

mes application se bloque souvent dans cette boucle for:App plante souvent dans une boucle for

for (int a = 0; a <= 20; a++) { 
     NSString * foo = [[NSString alloc]initWithString:[[newsStories objectAtIndex:arc4random() % [newsStories count]] objectForKey:@"title"]]; 
     foo = [foo stringByReplacingOccurrencesOfString:@"’" withString:@""]; 
     foo = [[foo componentsSeparatedByCharactersInSet:[[NSCharacterSet letterCharacterSet] invertedSet]] componentsJoinedByString:@" "]; 
     foo = [foo stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 
     textView.text = [textView.text stringByAppendingString:[NSString stringWithFormat:@"%@ ", foo]]; 
    } 

Le code change un NSString d'un NSDictionary et il ajoute dans un textView. Parfois, il se bloque pour la première fois en utilisant la boucle for. Qu'est-ce que j'ai mal?

+0

Quel accident obtenez-vous? –

+0

Il n'y a pas de message d'erreur dans le NSLog. – Flocked

+0

Quel est le crash? ça dit quoi? Pas dans un NSLog mais dans le débogueur. – Chuck

Répondre

2

initWithString: déclenche une exception si vous passez un argument nul, donc si votre newsStories élément dictionnaire arrive à manquer son titre, cela causera un crash (sauf si vous attrapez l'exception ailleurs).

Essayez le fractionnement de la partie qui récupère le titre et assurez-vous qu'il est non nul avant de passer à initWithString:

NSString *titleString = [[newsStories objectAtIndex:arc4random() % [newsStories count]] objectForKey:@"title"]; 

if (!titleString) 
    titleString = @"<TITLE IS EMPTY>"; 

foo = [[[NSString alloc] initWithString: titleString] autorelease]; 

Par ailleurs, si l'objet de titre newsStories élément dictionnaire n'est pas une instance NSString, que planterait initWithString: aussi.

0

Essayez de déclarer NSString * foo avant la boucle. Quelque chose comme ceci:

NSString *foo; 
for(int a = 0; a <= 20; a++) 
{ 
foo = [NSString stringWithString:[some code here]]; 
. 
. 
. 
[do something to foo] 
} 

J'ai rencontré des erreurs plusieurs fois en ne faisant pas cela.

+0

Pourquoi est-ce important si foo n'est pas utilisé en dehors de la boucle? –

+0

Etrange: Avec ce code, j'ai eu cinq runs for-loop et il ne s'est pas crashé. Ensuite, il se bloque. J'ai recommencé le programme et maintenant il se bloque immédiatement. – Flocked

+0

Je n'ai pas une bonne réponse pour vous. Encore. C'est une solution qui a fonctionné pour moi plusieurs fois. Une chose qui m'inquiète, c'est que foo n'est pas sorti à la fin de la boucle. Le paramètre de propriété du champ de texte doit gérer la gestion de la mémoire de foo une fois la propriété définie. En utilisant la méthode de classe "stringWithString:" vous devriez obtenir le contrôle de la mémoire sous contrôle avec un minimum de modifications à votre code. –

0

En fait, déclarer le NSString dans la boucle n'a pas d'importance et il est bon de contrôler l'objet dans le domaine de la boucle. J'ai trouvé qu'il y avait une fuite de mémoire dans votre code que le nsstring ne devait plus être publié après que vous ayez créé. Donc, premièrement, vous devriez contrôler l'objet nsstring et vous assurer qu'il n'y a pas de fuite de mémoire, après l'avoir alloué, il était de votre responsabilité de le libérer. Deuxièmement, je ne suis pas sûr de ce que dans votre tableau nommé "newsStories", pourriez-vous s'il vous plaît télécharger du code pour montrer quelques détails sur ce tableau? Tels que le nombre de ce tableau ou les éléments dans le tableau.

0

Pourquoi utilisez-vous NSString? C'est une classe immuable qui signifie que vous ne pouvez pas le changer et pourtant vous le changez plusieurs fois. Essayez d'utiliser NSMutableString.

+0

Le code donné ne mute pas réellement l'objet NSString, mais réattribue plutôt 'foo' pour pointer vers un nouvel objet NSString auto-libéré (ne laissant aucun pointeur sur les objets string précédemment utilisés). – Isaac

+0

Isaac, peux-tu m'expliquer ça? Quand il exécute: foo = [foo stringByReplacingOccurrencesOfString: @ "'" withString: @ ""]; comment est-ce que cela ne mute pas la chaîne foo? J'ai toujours créé une nouvelle chaîne dans ce cas comme ceci: NSString * foo2 = [foo stringByReplacingOccurrencesOfString: @ "'" withString: @ ""]; – regulus6633

0

Je suppose que vous travaillez dans un environnement de comptage de référence, c'est-à-dire que la récupération de place est désactivée.

Tout d'abord, essayez de changer la première ligne dans la boucle:

NSString * foo = [NSString stringWithString:[[newsStories objectAtIndex:arc4random() % [newsStories count]] objectForKey:@"title"]]; 

En utilisant la méthode de classe stringWithString: au lieu de alloc et initWithString: donne une place NSString autoreleased d'une chaîne avec retenue count = 1. Cela devrait résoudre la fuite de mémoire mentionnée dans les commentaires et/ou d'autres réponses. Cependant, chaque opération foo = à l'intérieur de la boucle crée une autre NSString auto-libérée, donc à chaque itération de la boucle, vous créez 3 (votre version) ou 4 (si vous faites la modification ci-dessus) des chaînes auto-libérées, ce qui pourrait sur les itérations et causer des ennuis. À cause de cela, il pourrait aider à créer et libérer un pool autorelease dans votre boucle:

for (int a = 0; a <= 20; a++) { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    NSString * foo = [NSString stringWithString:[[newsStories objectAtIndex:arc4random() % [newsStories count]] objectForKey:@"title"]]; 
    foo = [foo stringByReplacingOccurrencesOfString:@"’" withString:@""]; 
    foo = [[foo componentsSeparatedByCharactersInSet:[[NSCharacterSet letterCharacterSet] invertedSet]] componentsJoinedByString:@" "]; 
    foo = [foo stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 
    textView.text = [textView.text stringByAppendingString:[NSString stringWithFormat:@"%@ ", foo]]; 
    [pool release]; 
} 
Questions connexes