好的,我有一个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语句中释放它,问题不存在但是我会有内存泄漏? ?我总是可以保持数组并删除/添加对象,但我想知道为什么这不起作用:) 欢呼声
答案 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
。