使用NSMutableArray的iphone EXC_BAD_ACCESS

All*_*lan 5 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
}
Run Code Online (Sandbox Code Playgroud)

在我的SearchViewController.h我有:

@property (nonatomic,retain) NSMutableArray *listData;
Run Code Online (Sandbox Code Playgroud)

在我的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;
}
Run Code Online (Sandbox Code Playgroud)

它崩溃了:

self.listData = [delegate.data getListTwo];
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

Ada*_*eld 7

这是你的问题:

if (self.listData !=nil)
{
    [self.listData release];
}
Run Code Online (Sandbox Code Playgroud)

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

- (void) setListData:(NSMutableArray *)listData
{
    [listData retain];
    [self->listData release];
    self->listData = listData;
}
Run Code Online (Sandbox Code Playgroud)

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

因此,这意味着无论何时设置属性,您都不必担心释放旧值 - setter会为您执行此操作.因为你正在做一个额外的版本,所以在你实际使用它之前,对象就会被释放,所以只要你在它被释放后使用它,你就得到了EXC_BAD_ACCESS.