使用NSMutableArray的iphone EXC_BAD_ACCESS

时间:2009-07-07 12:35:57

标签: iphone objective-c

好的,我有一个UIViewTable和一个带有两个范围按钮的UISearchBar。我的想法是,当我按下范围按钮时,UIViewTable的数据源会发生变化,但我得到了 EXC_BAD_ACCESS错误。

我的UIViewController SearchViewController.m中有以下代码:

- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange: (NSInteger) selected scope
{
    MyAppDelegate *delegate = (MyAppDelegate *) [[UIApplicationsharedApplication] delegate];
    if (self.listData != nil) {
        [self.listData release];
    }
    if (selectedScope == 0) {
        self.listData = [delegate.data getListOne];
    }
    else {
        self.listData = [delegate.data getListTwo];
    }
}

- (void) viewDidLoad {
    MyAppDelegate *delegate = (MyAppDelegate*) [[UIApplication sharedApplication] delegate];
    self.listData = [delegate.data getListOne];

    //some other unrelated code
}

在我的SearchViewController.h中我有:

@property (nonatomic,retain) NSMutableArray *listData;

在我的Data.m中我有:

-(NSMutableArray *) getListOne {
     NSMutableArray *list = [[NSMutableArray alloc] initWithObjects:@"test1",
                                                                    @"test2",
                                                                    nil];
     [list autorelease];
     return list;
}

-(NSMutableArray *) getListTwo {
     NSMutableArray *list = [[NSMutableArray alloc] initWithObjects:@"test3",
                                                                    @"test4",
                                                                    nil];
     [list autorelease];
     return list;
}

它崩溃了:

self.listData = [delegate.data getListTwo];

当我设置它崩溃的属性时,我检查了它。我的理解是,当我在Data.m中创建新的NSMutableArray时,我将其指定为自动释放。

当视图加载时,我将它分配给我的listData,因为我正在访问已保留的属性,所以引用计数会递增(因此它现在有2个待处理的自动释放)。

当我按下按钮更改数据源时,我也检查是否存在listData(它总是会存在),释放它以便旧的NSMutableArray计数器将为0(假设已发生自动释放)。

然后我得到一个新的NSMutableArray并将其设置为此属性...我的理解是否正确?我在这个简单的问题上花了太长时间:(

哦我也创建了另一个没有连接到tableView的NSMutableArray并且仍然遇到同样的问题,如果我不在if语句中释放它,问题不存在但是我会有内存泄漏? ?我总是可以保持数组并删除/添加对象,但我想知道为什么这不起作用:) 欢呼声

1 个答案:

答案 0 :(得分:7)

这是你的问题:

if (self.listData !=nil)
{
    [self.listData release];
}

您不需要执行此检查 - 由于您使用listData属性声明了retain属性,因此合成的setter会自动处理release旧的价值。合成的setter看起来像这样:

- (void) setListData:(NSMutableArray *)listData
{
    [listData retain];
    [self->listData release];
    self->listData = listData;
}

请注意以下几点:释放旧值,并保留新值。此外,在自我分配的情况下,保留在发布之前发生:如果您分配相同的值,则不希望它过早地被释放。另请注意,如果新值或旧值为nil,则不会发生任何不良情况,因为Objective-C明确允许您向nil发送消息,但不起作用。

因此,这意味着无论何时设置属性,您都不必担心释放旧值 - setter会为您执行此操作。因为您正在进行额外的发布,所以在您实际使用它之前,该对象将被释放,所以只要在它被取消分配后使用它,您就会获得EXC_BAD_ACCESS