2011-05-12 156 views
2

我一直在嘗試爲我的朋友爲樂隊創建我自己的應用程序,並且我一直在嘗試使用自定義TableViewCell來查看網站上出現的新聞報道。我的主要目標是從網站獲取所有數據,將其存儲在NSMutableArray中,然後將其顯示在我的自定義單元格中。UITableView在滾動時崩潰

當它加載第5-6個單元格時,應用程序運行良好。但是,當我開始滾動時,應用程序崩潰。我已經指出了cellForRowAtIndexPath:方法。使用GDB,我也發現在創建我的NSMutableArray數據之後,一旦程序運行,滾動後,我的數組似乎就會自動釋放。我不知道爲什麼會發生這種情況。下面是我對我的代碼迄今:

在HomeViewController.h:

@interface HomeViewController : UIViewController { 
    NSArray *results; 
    NSMutableArray *titles; 
    NSMutableArray *dates; 
    NSMutableArray *entries; 
} 

@property (nonatomic, retain) NSMutableArray *titles; 
@property (nonatomic, retain) NSMutableArray *dates; 
@property (nonatomic, retain) NSMutableArray *entries; 

@end 

在HomeViewController.m:

- (void)viewDidLoad { 
[super viewDidLoad]; 
titles = [[NSMutableArray alloc] init]; 
dates = [[NSMutableArray alloc] init]; 
entries = [[NSMutableArray alloc] init]; 

while((i+1) != endIndex){ 
    NSString *curr_title = [[NSString alloc] init]; 
    NSString *curr_date = [[NSString alloc] init]; 
    NSString *curr_entry = [[NSString alloc] init]; 

    //do some character iterations across a string 

    [titles addObject:curr_title]; 
    [dates addObject:curr_date]; 
    [entries addObject:curr_entry]; 

    [curr_title release]; 
    [curr_date release]; 
    [curr_entry release]; 
} 
} 

//更多在這裏的代碼,刪除

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

static NSString *CellIdentifier = @"NewsCell"; 


NewsCell *cell = (NewsCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

if (cell == nil) { 
    NSArray *topLevelObjects = [[NSBundle mainBundle] 
           loadNibNamed:@"NewsCell" 
           owner:self options:nil]; 
// cell = [topLevelObjects objectAtIndex:0]; 
    for(id currentObject in topLevelObjects){ 
     if([currentObject isKindOfClass:[UITableViewCell class]]){ 
      cell = (NewsCell *)currentObject; 
      break; 
     } 
    } 

} 
NSLog(@"%d", indexPath.row); 
NSLog(@"%d", titles.count); 
cell.cellTitle.text = [titles objectAtIndex:indexPath.row]; 
cell.datePosted.text = [dates objectAtIndex:indexPath.row]; 
cell.preview.text = [entries objectAtIndex:indexPath.row]; 

return cell; 
} 

同樣,前5-6個細胞出現。有一次,我滾動,我試圖這樣做po titles和得到這個錯誤:

Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_PROTECTION_FAILURE at address: 0x00000009 0x011b309b in objc_msgSend()

我試過在initWithNibName:分配數組,但似乎並沒有做太多。我試過移動viewDidLoad:中的所有代碼,然後調用[super viewDidLoad],它也產生了相同的結果。對不起,這是很長的,但我想人們需要看我的代碼。

回答

2

我沒有看到你發佈的代碼有任何明顯的錯誤。嘗試enabling the NSZombieEnabled environment variable。這可以防止對象被釋放,以便在應用程序「崩潰」時可以確定哪個對象導致了問題。

另外,您應該將期望的對象分配給您的類的IBOutlet屬性,而不是循環遍歷loadNibNamed:owner:options返回的對象。一個例子見Loading Custom Table-View Cells From Nib Files


以下是從您發佈的新代碼提取:

NSString *curr_title = [[NSString alloc] init]; 

//do some character iterations across a string 

[titles addObject:curr_title]; 

[curr_title release]; 

的NSString不可改變(如的NSMutableString)。你是否有意將空字符串添加到titles數組中?


在回答您的評論:stringByAppendingString創建一個新的自動釋放的NSString對象。

NSString *curr_title = [[NSString alloc] init]; 

// this leaks the original NSString object (curr_title no longer points to it); 
// curr_title now points to a new, autoreleased NSString 
curr_title = [curr_title stringByAppendingString:@"..."]; 

[titles addObject:curr_title]; 

// releasing the autoreleased NSString will cause your application to crash! 
[curr_title release]; 
+0

感謝您的快速響應!我曾嘗試使用NSZombiesEnabled,但它並沒有提供足夠奇怪的信息。我用過Instruments,它確實說過「有一個Objective-C消息被髮送到地址爲0x5e70870的釋放對象(殭屍)。」它指出了一些自動釋放的東西,所以我正在研究這一點。它似乎仍然像我的數組發佈不知何故。 – SpacePyro

+0

同時檢查您添加到陣列的對象是否被過度釋放。 – titaniumdecoy

+0

我增加了一些代碼(上面的編輯)。我不認爲他們是過度發佈的,但不知何故,他們是(我仍然試圖獲得Objective-c的懸掛!),我肯定會解決這個問題。 – SpacePyro

0

這個問題可能與NewsCell的實現有關,您所有的屬性都被保留了嗎?

此外,任何原因HomeViewController是繼承UIViewController而不是UITableViewController?

這應該只是罰款:

NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"NewsCell" owner:self options:nil]; 
cell = [topLevelObjects objectAtIndex:0]; 
+1

這些數組沒有被過度保留。沒有使用合成的setter方法。 – Leehro

+0

沒有必要繼承UITableViewController以在UIViewController中使用UITableView。 UITableViewController可以很方便,但它的代價是靈活性。 – titaniumdecoy

+0

好的;我假設你打算評論我的帖子。固定! – titaniumdecoy

0

* EXC_BAD_ACCESS *是一個明確的信號,你的目標之一是在得到釋放(或沒有正確保留)。 NSZombieEnabled在這裏是你的朋友,就像titaniumdecoy所說的那樣 - 找出目標是被釋放的是戰鬥的一半。只要確保在發佈應用程序之前關閉它,因爲(如鈦德科指出的)它可以防止物體被釋放。

我通常使用NSZombieEnabled和良好放置的斷點的組合(以便我可以遍歷代碼直到它崩潰)找出問題在代碼中出現的位置。然後通常是回溯的簡單問題,以找出對象被釋放的位置。