UIButton 接触 IBAction 导致 EXC_BAD_ACCESS 与 ARC

发布于 2025-01-01 03:40:58 字数 2432 浏览 1 评论 0原文

StackOverflow 上有一些问题,其中用户遇到了与我相同的问题。然而,他们的解决方案都不适合我的情况。 (请参阅此处此处此处这里了解一些我读过但没有发现有帮助的问题。)

就我而言,我有一个 NIB,其中有几个UIButton,带有关联的控制器视图。该视图对于我的项目来说相对较旧,直到今天我才能够毫无问题地使用这些按钮。在进行了一些与按钮行为无关的代码更改后,我遇到了一个错误,导致应用程序崩溃,破坏了 main() 函数中的代码,并给了我一个 每当我触摸视图上的任何按钮时,都会出现 EXC_BAD_ACCESS 错误消息。

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

我的项目正在使用自动引用计数,我以前没有见过这个错误。此外,我没有修改 NIB,也没有修改与按钮关联的 IBAction,所以我不知道是什么导致了这种情况。停止该错误的唯一方法是取消 NIB 中的 UIButton 与控制器视图头文件中定义的 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 时添加的标准自动生成代码。

我可以做什么来解决或诊断这个问题?

There have been a few questions on StackOverflow where users have experienced the same problem as I am having. However, none of their solutions fit my case. (See here, here, here and here for some of the SO questions I've read but have not found helpful.)

In my case, I have a NIB that has a couple UIButtons, with an associated Controller View. The view is relatively old to my project and I've been able to use these buttons without any trouble until today. After making a few code changes that were not related to the button behavior, I've run into an error that crashes the app, breaks the code at the main() function and gives me an EXC_BAD_ACCESS error message whenever I touch any of the buttons on my View.

How or why might this happen? I've actually commented out almost all functional code, especially that which I modified earlier today and I still can't stop the error from occurring.

My project is using Automatic Reference Counting and I haven't seen this error before. Furthermore, I did not modify the NIB, nor the IBAction associated with the buttons so I don't see what would cause this. The only way to stop the error is to unlink my UIButtons in my NIB to the IBActionmethods defined in my Controller View header file.

The only "unique" aspect of my use-case is that I load either one or two instances of this view, within another sub view controller. The number of instances of the broken view that are loaded is contingent on the number of objects in an array. Below is the code that I use to instantiate and load these views as subviews of another view.

//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;
}

This works perfectly and, previously, hadn't even caused any trouble with the buttons that were on the associated view, however, now all UIButtons crash the app when tapped.

The initialization function for SubViewController, as well as the viewDidLoad method contain nothing other than the standard, auto-generated code that is added when you create a new ViewController.

What can I do to either fix or diagnose this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

莫言歌 2025-01-08 03:40:58

请参阅我在代码中的注释:

{
    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 实例保持在周围以接收按钮点击。

See my comments in your code:

{
    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
}

To fix this, add each SubViewController instance to an array owned by the master view controler. That will keep the SubViewController instances around to receive the button taps.

给不了的爱 2025-01-08 03:40:58

确保在您的 dealloc 中调用:

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

尽管您认为 ARC 中不需要“dealloc”,但由于 iccir 的解释,您需要这样做。

Make sure in your dealloc you call:

[button removeTarget:nil
action:NULL
forControlEvents:UIControlEventAllEvents];

Even though you though you didn't need "dealloc's" in ARC, you do because of what iccir explained.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文