2011-05-12 153 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和良好放置的断点的组合(以便我可以遍历代码直到它崩溃)找出问题在代码中出现的位置。然后通常是回溯的简单问题,以找出对象被释放的位置。