应用程序经常在for循环中崩溃

时间:2010-03-22 02:41:59

标签: objective-c nsstring for-loop

我的应用程序经常在这个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]];
    }

代码从NSDictionary更改NSString并将其添加到textView中。有时它会在第二次使用for循环时崩溃。我错了什么?

5 个答案:

答案 0 :(得分:2)

如果你传递一个nil参数,

initWithString:会引发一个异常,所以如果你的newsStories字典项碰巧缺少它的标题,那将导致崩溃(除非你在其他地方捕获异常)。

尝试拆分检索标题的部分,并在将其传递给initWithString之前确保它是非零的:

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

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

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

或者,如果newsStories字典项的标题对象不是NSString实例,那么也会使initWithString:崩溃。

答案 1 :(得分:0)

尝试在循环之前声明NSString * foo。像这样:

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

如果不这样做,我会遇到几次错误。

答案 2 :(得分:0)

实际上,在循环中声明NSString无论如何都可以控制循环域中的对象。我发现代码中存在内存泄漏,因此创建后不再释放nsstring。所以,首先,您应该控制nsstring对象并确保没有内存泄漏,在分配之后,您有责任释放它。其次我不知道你的数组中有什么名为“newsStories”,请你上传一些代码来展示这个数组的一些细节吗?例如此数组的计数或数组中的项目。

答案 3 :(得分:0)

为什么使用NSString?这是一个不可变的类,这意味着你不能改变它,但你多次改变它。尝试使用NSMutableString。

答案 4 :(得分:0)

我假设您正在使用引用计数环境 - 即垃圾收集已关闭。

首先,尝试将循环内的第一行更改为:

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

使用类方法stringWithString:而不是allocinitWithString:会产生一个自动释放的NSString而不是一个带有retain count = 1的字符串。这应该可以解决注释中提到的内存泄漏问题。 /或其他答案。

但是,循环内的每个foo =操作都会创建另一个自动释放的NSString,因此在循环的每次迭代中,您创建3(您的版本)或4(如果您进行上述更改)自动释放的字符串,这可能会在迭代中积累并造成麻烦。因此,在循环中创建和释放自动释放池可能会有所帮助:

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];
}