UIButton触及IBAction导致EXC_BAD_ACCESS与ARC

时间:2012-02-01 21:34:09

标签: objective-c ios debugging exc-bad-access

StackOverflow上有一些问题,用户遇到了与我相同的问题。但是,他们的解决方案都不适合我的情况。 (请参阅herehereherehere,了解我之前阅读但未发现有用的一些问题。)

在我的情况下,我有一个NIB,它有几个UIButton s,带有一个关联的Controller View。该视图对我的项目来说相对较老,直到今天我才能毫无困难地使用这些按钮。在进行了与按钮行为无关的一些代码更改后,我遇到了导致应用崩溃的错误,破坏了main()函数中的代码,并给出了EXC_BAD_ACCESS错误每当我触摸视图上的任何按钮时都会显示消息。

这种情况如何或为何会发生?我实际上已经注释掉了几乎所有功能代码,特别是我今天早些时候修改过的代码,但我仍然无法阻止错误的发生。

我的项目正在使用自动引用计数,之前我还没有看到此错误。此外,我没有修改NIB,也没有修改与按钮相关联的IBAction所以我不知道会导致这种情况的原因。停止错误的唯一方法是取消我的NIB中的UIButton与我的Controller View头文件中定义的IBAction方法的链接。

唯一的"独特"我的用例的一个方面是我在另一个子视图控制器中加载此视图的一个或两个实例。加载的断开视图的实例数取决于数组中的对象数。下面是我用来实例化这些视图并将其作为另一个视图的子视图加载的代码。

//Called else where, this starts the process by creating a view that 
//will load the problematic view as a sub-view either once or twice.
- (id)initWithPrimarySystemView:(SystemViewController *)svc
{
    //First we create our parent, container view.
    self = [super initWithNibName:@"ContainerForViewInstaniatedFromArrayObjs" bundle:nil];
    if (self) 
    {
        //Assign parent DataModel to local instance
        [self setDataModel:((DataModelClass*)svc.DataModel)];
        for (AnotherModel* d in DataModel.ArrayOfAnotherModels)
        {
            //Instantiate the SubViewController.
            SubViewController* subsvc = [[SubViewController alloc] 
                                            initWithNibName:@"Subview" 
                                          bundle:nil 
                                          subviewPosition:d.Position ];

            //Add the SubViewControllers view to this view.
            [subsvc.view setFrame:CGRectMake((d.Position-1)*315, 0, 315, 400)];
            [self.view addSubview:subsvc.view];
        }
        [self setDefaultFrame: CGRectMake(0, 0, 640, 400)];
    }
    return self;
}

这非常有效,而且以前甚至没有对关联视图上的按钮造成任何麻烦,但是,现在所有UIButton都会在点击时崩溃应用程序。

SubViewController的初始化函数以及viewDidLoad方法除了在创建新的ViewController时添加的标准自动生成代码之外什么都没有。

我可以做些什么来修复或诊断此问题?

2 个答案:

答案 0 :(得分:8)

在您的代码中查看我的评论:

{
    SubViewController* subsvc = [[SubViewController alloc] initWithNibName:@"Subview" bundle:nil subviewPosition:d.Position ];
    //!i: By default, subsvc is a __strong pointer, so your subview has a +1 retain count
    //    subsvc owns subsvc.view, so subsvc.view has a +1 retain count as well

    //Add the SubViewControllers view to this view.
    [subsvc.view setFrame:CGRectMake((d.Position-1)*315, 0, 315, 400)];

    [self.view addSubview:subsvc.view];
    //!i: This bumps subsvc.view to +2, as self.view strong-references it

    //!i: subsvc is going out of scope, so the reference count on subsvc will drop
    //    to 0 and it is dealloc'd.  subsvc.view's retain count drops to +1, as it
    //    is still referenced by self.view
    //
    //    Most likely, in -[SubViewController dealloc], you were not doing a 
    //    setTarget:nil, setAction:nil on the button.  Thus, the button now 
    //    has a dangling pointer and will crash when hit
}

要解决此问题,请将每个SubViewController实例添加到主视图控制器拥有的阵列中。这将使SubViewController实例保持接收按钮水龙头。

答案 1 :(得分:1)

请确保在你的dealloc中打电话:

[button removeTarget:nil               动作:NULL     forControlEvents:UIControlEventAllEvents];

即使你在ARC中不需要“dealloc”,但是因为iccir解释了这一点。