iOS - EXC_BAD_ACCESS错误

3

我正在开发一款iPhone/iPod应用程序。以下代码是UIViewController的.m文件。我得到了以下结果:

Thread 1: EXC_BAD_ACCESS (code=2......

当我执行以下代码行时:
cell.textLabel.text = [datasource objectAtIndex:indexPath.row];

我理解通常出现这种情况是因为你在释放对象之后尝试访问它,但在我访问它之前我并没有释放它。下面是完整的代码,请帮忙看一下!

非常感谢您的帮助!

#import "HomePage.h"
#import "HusbandryRecordsMain.h"
#import "TaskManagerMain.h"
#import "AnimalInventoryMain.h"
#import "FeedInventoryMain.h"

@implementation HomePage
@synthesize options, datasource;

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad {
    [self setupArray];
    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.
}

-(void)setupArray{
    options = [NSMutableArray  arrayWithObjects:@"Husbandry Records", @"Task Manager", @"Feeder Inventory", @"Animal Inventory", nil];

    datasource = options;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    //#warning Incomplete method implementation.
    // Return the number of rows in the section.
    return 4;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";

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

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];    
    }

    [[cell textLabel] setBackgroundColor:[UIColor clearColor]];
    [[cell detailTextLabel] setBackgroundColor:[UIColor clearColor]];

    // THE FOLLOWING LINE IS THROWING THE ERROR!
    cell.textLabel.text = [datasource objectAtIndex:indexPath.row]; 

    //Arrow 
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    return cell;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    if (indexPath.row == 0){
        HusbandryRecordsMain *hrm = [self.storyboard instantiateViewControllerWithIdentifier:@"Husbandry Records - Main"];
        [self.navigationController pushViewController:hrm animated:YES];
    }
    else if (indexPath.row == 1){
        TaskManagerMain *tmm = [self.storyboard instantiateViewControllerWithIdentifier:@"Task Manager - Main"];
        [self.navigationController pushViewController:tmm animated:YES];
    } 
    else if (indexPath.row == 2){
        FeedInventoryMain *fim = [self.storyboard instantiateViewControllerWithIdentifier:@"Feeder Inventory - Main"];
        [self.navigationController pushViewController:fim animated:YES];
    }  
    else if (indexPath.row == 3){
        AnimalInventoryMain *aim = [self.storyboard instantiateViewControllerWithIdentifier:@"Animal Inventory - Main"];
        [self.navigationController pushViewController:aim animated:YES];
    }

    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

//----------------------TABLEVIEWCELL HEIGHT -------------------------------------------

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

    return 70;

}

- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

@end

4
除非有非常充分的理由,否则请使用ARC。 - zaph
1
如果您刚开始学习飞行,请不要使用弧线。 - NCFUSN
2个回答

5
-(void)setupArray{
    options = [NSMutableArray  arrayWithObjects:@"Husbandry Records", @"Task Manager", @"Feeder Inventory", @"Animal Inventory", nil];

    datasource = options;
}

你直接将一个自动释放的对象分配给datasource实例变量,然后在崩溃的代码行中释放后尝试使用它。如果打开了Zombie检测,很可能会直接捕获到这个问题。同时,静态分析器(build and analyze)也应该能够捕获到这个问题。(当然,如果你启用了ARC,则情况可能不同...)

什么是僵尸检测?我不熟悉这个。ARC已关闭 - 我应该保持开启吗?好的,那么我该如何解决这个问题? - comead
2
你需要retain选项;可以使用self.datasource = options;或者datasource = [options retain];。如果这是新代码,你应该总体上使用ARC。然而,你真的应该去学习Objective-C和内存管理的基础知识,否则这将是许多问题/崩溃的第一个,会引起头痛(先学走再学跑)。 - bbum

0

你的文件选项和数据源是什么类型?还可以尝试使用self.options等。


数据源是一个NSArray,选项是NSMutableArray。 - comead
好的。为什么你需要两个数组来保存你的数据?你可能已经保留了它们(使用strong或retain)。只使用self.option,并不要忘记在dealloc方法中释放它。 - NCFUSN
返回4的语句可以改为返回[self.option count]。 - NCFUSN
谢谢!dealloc方法是什么样子的?我没有,我知道内存管理不好:/我只是没有多少使用obj-c。 - comead
在你的.m文件中的某个地方放置以下方法; -(void)dealloc { [option release];[super dealloc];} 这意味着你的责任是在这个方法中释放保留的对象。否则,你将会产生内存泄漏。 - NCFUSN
选项和数据源的类型与崩溃无关;崩溃非常直接。建议“尝试某些东西”来解决问题,而没有说明为什么这样做会起作用/解决问题,这是一个让问题变得更糟的绝对方法... - bbum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接