简体   繁体   English

使用NSMutableArray的iphone EXC_BAD_ACCESS

[英]iphone EXC_BAD_ACCESS with NSMutableArray

Ok so I have a UIViewTable and a UISearchBar with two scope buttons. 好的,我有一个UIViewTable和一个带有两个范围按钮的UISearchBar。 The idea being that when I press a scope button the datasource for UIViewTable gets changed but I am getting EXC_BAD_ACCESS error. 我的想法是,当我按下范围按钮时,UIViewTable的数据源会发生变化,但我收到EXC_BAD_ACCESS错误。

I have the following code in my UIViewController SearchViewController.m: 我的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
}

in my SearchViewController.h I have: 在我的SearchViewController.h我有:

@property (nonatomic,retain) NSMutableArray *listData;

in my Data.m I have: 在我的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;
}

It crashes on: 它崩溃了:

self.listData = [delegate.data getListTwo];

I checked that its when I am setting the property that it crashes. 当我设置它崩溃的属性时,我检查了它。 My understanding is that when I create the new NSMutableArray in Data.m I assign it autorelease as I should. 我的理解是,当我在Data.m中创建新的NSMutableArray时,我将其指定为自动释放。

When the view loads I assign it to my listData and since I am accessing the property which has retain then the reference count is incremented (so its now 2 pending auto release). 当视图加载时,我将它分配给我的listData,因为我正在访问已保留的属性,所以引用计数递增(因此它现在是2个待处理的自动释放)。

When I press the button to change the data source I check too see if listData exists (which it always will), release it so that the old NSMutableArray counter will be 0 (assuming autorelease has occured). 当我按下按钮更改数据源时,我也检查是否存在listData(它总是会存在),释放它以便旧的NSMutableArray计数器将为0(假设已经发生自动释放)。

Then I get a new NSMutableArray and set it to this property... is my understanding correct? 然后我得到一个新的NSMutableArray并将其设置为此属性...我的理解是否正确? I have spent far too long on this simple problem :( 我在这个简单的问题上花了太长时间:(

oh also I did create another NSMutableArray that was not connected to the tableView and still get the same problem, also if I don't release it in my if statement the problem does not exist but I will then have a memory leak?? 哦,我也创建了另一个没有连接到tableView的NSMutableArray并仍然得到同样的问题,如果我不在我的if语句中释放问题不存在但是我会有内存泄漏? I could always just keep the array and remove/add objects but I want to know why this is not working :) cheers 我总是可以保持数组并删除/添加对象,但我想知道为什么这不起作用:)欢呼

This is your problem: 这是你的问题:

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

You don't need to do this check -- by virtue of the fact that you declared the listData property with the retain property, the synthesized setter automatically takes care of release ing the old value. 您不需要执行此检查 - 由于您使用retain属性声明了listData属性,因此合成的setter会自动负责release旧值。 The synthesized setter would look something like this: 合成的setter看起来像这样:

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

Note a few things here: the old value is released, and the new value is retained. 请注意以下几点:释放旧值,并保留新值。 Further, the retain happens before the release, in case of self-assignment: if you assign the same value, you don't want it to be prematurely deallocated. 此外,保留发布之前发生,如果是自我赋值:如果指定相同的值,则不希望它过早地被释放。 Also note that if either the new or old value is nil , nothing bad happens, since Objective-C explicitly permits you to send messages to nil , having no effect. 另请注意,如果new或old值为nil ,则不会发生任何不良情况,因为Objective-C明确允许您将消息发送到nil ,不起作用。

So, this means that whenever you set the property, you don't need to worry about releasing the old value -- the setter does that for you. 因此,这意味着无论何时设置属性,您都不必担心释放旧值 - setter会为您执行此操作。 Because you are doing an extra release, the object is getting deallocated before you're actually done using it, so as soon as you use it after it's been deallocated, you get the EXC_BAD_ACCESS . 因为您正在进行额外的发布,所以在您实际使用它之前,该对象将被释放,因此在您取消分配之后使用它时,您将获得EXC_BAD_ACCESS

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM