2010-03-22 23 views
0

我的應用程序崩潰中經常死機這個for循環:應用在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循環時崩潰。我錯了什麼?

+0

你會發生什麼事故? – 2010-03-22 02:48:29

+0

NSLog中沒有崩潰消息。 – Flocked 2010-03-22 02:49:54

+0

什麼是崩潰?它說什麼?不在NSLog中,但在調試器中。 – Chuck 2010-03-22 02:51:18

回答

2

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:以及。

0

嘗試在循環之前聲明NSString * foo。這樣的事情:

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

我沒有這樣做,遇到錯誤幾次。

+0

如果在循環之外不使用foo,爲什麼會這麼重要? – 2010-03-22 02:53:19

+0

奇怪:用這段代碼,我得到了五個for-loop運行,它沒有崩潰。然後它崩潰。我再次啓動程序,現在它立即崩潰。 – Flocked 2010-03-22 02:56:17

+0

我對你沒有很好的答案。然而。這是一個多次爲我工作的解決方案。 有一件令我擔心的事情是foo沒有被釋放到循環的結尾。一旦屬性被設置,文本字段的屬性設置應該處理foo的內存管理。通過使用類方法「stringWithString:」,您應該通過對代碼進行最小限度的更改來控制內存管理。 – 2010-03-22 02:59:43

0

實際上,在循環中聲明NSString並不重要,它可以很好地控制循環域中的對象。我發現你的代碼中存在內存泄漏,你創建後nsstring不再被釋放。所以,首先,你應該控制nsstring對象,確保沒有內存泄漏,在你分配之後,你有責任釋放它。其次,我不確定你的數組中名爲「newsStories」的是什麼,你能否上傳一些代碼來顯示關於這個數組的一些細節?如該數組的計數或數組中的項目。

0

你爲什麼使用NSString?這是一個不可變的類,這意味着你不能改變它,但你多次改變它。嘗試使用NSMutableString。

+0

給定的代碼實際上並沒有改變NSString對象,而是將'foo'重新指定爲指向新的自動發佈的NSString對象(不留下指向先前使用的字符串對象的指針)。 – Isaac 2010-03-22 09:31:42

+0

艾薩克,你能解釋一下嗎?當他執行: foo = [foo stringByReplacingOccurrencesOfString:@「'」withString:@「」]; 這是怎麼不突變字符串foo?在這種情況下,我總是創建一個新的字符串: NSString * foo2 = [foo stringByReplacingOccurrencesOfString:@「'」withString:@「」]; – regulus6633 2010-03-23 01:33:58

0

我假設你在引用計數的環境中工作 - 即垃圾收集已關閉。

首先,嘗試改變第一線內循環到:

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

使用類方法stringWithString:代替allocinitWithString:產生一個自動釋放的NSString而不是與保留計數= 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]; 
}