App crashes often in a for-loop
my app crashes often in this for-loop:
for (int a = 0; a <= 20; a++) {
NSString * foo = [[NSString alloc]initWithString:[[newsStories objectAtIndex:arc4random() % [newsStories count]] o开发者_JAVA百科bjectForKey:@"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]];
}
The code changes a NSString from a NSDictionary and adds it into a textView. Sometimes it first crashes in the second time using the for-loop. What did I wrong?
initWithString: raises an exception if you pass it a nil argument, so if your newsStories dictionary item happens to be missing its title, that will cause a crash (unless you're catching the exception elsewhere).
Try splitting off the part that retrieves the title and make sure it's non-nil before passing it to initWithString:
NSString *titleString = [[newsStories objectAtIndex:arc4random() % [newsStories count]] objectForKey:@"title"];
if (!titleString)
titleString = @"<TITLE IS EMPTY>";
foo = [[[NSString alloc] initWithString: titleString] autorelease];
Alternatively, if the newsStories dictionary item's title object isn't an NSString instance, that would crash initWithString: as well.
Try declaring NSString *foo before the loop. Something like this:
NSString *foo;
for(int a = 0; a <= 20; a++)
{
foo = [NSString stringWithString:[some code here]];
.
.
.
[do something to foo]
}
I've run into errors a couple of times when not doing this.
Actually, declare the NSString in the loop does no matter and it is good to control object in the loop domain. I found there was a memory leak in your code that the nsstring was no longer to be released after you created. So, firstly, you should control the nsstring object and make sure there is no memory leak, after you alloc it, it was your responsibility to release it. Secondly I'm not sure what in your array named "newsStories", would you please upload some code to show some detail about this array? Such as the count number of this array or the items in the array.
Why are you using NSString? That's an immutable class which means you can't change it and yet you change it multiple times. Try using NSMutableString.
I'm assuming you're working in a reference-counted environment--that is, garbage collection is off.
First, try changing the first line inside the loop to:
NSString * foo = [NSString stringWithString:[[newsStories objectAtIndex:arc4random() % [newsStories count]] objectForKey:@"title"]];
Using the class method stringWithString:
instead of alloc
and initWithString:
yields an autoreleased NSString instead of a string with retain count = 1. This should solve the memory leak mentioned in the comments and/or other answers.
However, each foo =
operation inside the loop creates another autoreleased NSString, so in each iteration through the loop, you're creating 3 (your version) or 4 (if you make the above change) autoreleased strings, which could build up over the iterations and cause trouble. Because of this, it might help to create and release an autorelease pool inside your loop:
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];
}
精彩评论