我一直在尝试为我的朋友创建一个乐队的应用程序,我一直在尝试使用自定义TableViewCell来显示网站上的新闻文章。我的主要目标是从网站获取所有数据,将其存储在NSMutableArray中,然后在我的自定义单元格中显示。
应用程序在加载前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]
,它也产生了相同的结果。对不起,这太长了,但我想人们需要查看我的代码。
答案 0 :(得分:2)
我发现您发布的代码没有明显错误。试试enabling the NSZombieEnabled environment variable。这可以防止对象被释放,这样当您的应用程序“崩溃”时,您可以确定哪个对象导致了问题。
此外,您应该将所需对象分配给类的loadNibNamed:owner:options
属性,而不是循环遍历IBOutlet
返回的对象数组。有关示例,请参阅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];
答案 1 :(得分:0)
问题可能出在NewsCell的实施上,你的所有属性都被保留了吗?
另外,HomeViewController是UIViewController的子类而不是UITableViewController的任何原因?
这应该可以正常工作:
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"NewsCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
答案 2 :(得分:0)
* EXC_BAD_ACCESS *是一个确定的迹象,表明您的某个对象已被释放(或未正确保留)。 NSZombieEnabled 在这里是你的朋友,正如titdecoy所暗示的那样 - 弄清楚什么对象被释放是一半的战斗。请务必在发布应用程序之前将其关闭,因为(正如钛金属指出的那样)它会阻止对象被释放。
我通常使用NSZombieEnabled和放置良好的断点的组合(所以我可以遍历代码直到它崩溃)来找出问题在代码中出现的位置。然后通常只需回溯即可找出对象被释放的位置。