如何向另一个类中的 UIButton 添加操作 [英] How to add an action to a UIButton that is in another class

查看:27
本文介绍了如何向另一个类中的 UIButton 添加操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码编译良好,但由于无法识别的选择器发送到实例错误而崩溃.

The code below compiles fine, but crashes with an unrecognized selector sent to instance error.

我有一个继承自 UIViewController 的类:

I have one class that inherits from UIViewController:

class Controller: UIViewController {
    override func viewDidLoad() {
        let toolbarWrapper = CustomToolbarWrapper(view: view, target: self)
        let toolbar = toolbarWrapper.toolbarView
        view.addSubview(toolbar)

        ... Other code ...

    }
}

另一个类只是一个 UIView 的包装器并包含按钮:

And another class that is just a wrapper for a UIView and contains buttons:

class CustomToolbarWrapper {

    var toolbarView: UIView

    init(view: UIView, target: Any) {
        let height: CGFloat = 80
        toolbarView = UIView(frame: CGRect(x: 0, y: view.frame.height - height, width: view.frame.width, height: height))
        let button = UIButton()

        ... Some button layout code ...

        button.addTarget(target, action: #selector(CustomToolbar.buttonTapped(_:)), for: .touchUpInside)
        toolbarView.addSubview(button)
    }

    @objc static func buttonTapped(_ sender: Any) {
        print("button tapped")
    }
}

为了清楚起见,我省略了大量代码,保留了我认为必要的部分.我认为我的代码不起作用,因为我对 addTarget 函数中目标的工作方式有误解.通常,我只会使用 self 作为按钮操作的目标,所以我只是尝试将 self 从视图控制器传递到 CustomToolbarWrapper> 的 init 函数.

For the sake of clarity, I left out a large chunk of code and kept what I thought was necessary. I think that my code doesn't work because of my misunderstanding of the how the target works in the addTarget function. Normally, I would just use self as the target of my button's action, so I just tried to pass along self from the view controller to the CustomToolbarWrapper's init function.

我还尝试了什么:

将按钮的目标从 target 更改为 self,如下所示:

Changing the button's target from target to self like this:

button.addTarget(self, action: #selector(CustomToolbar.buttonTapped(_:)), for: .touchUpInside)

导致应用不再崩溃.但是,相反,我认为该行代码无法执行任何操作(出于某种原因不会引发错误?),因为尝试打印 button.allTargets 甚至 button.allTargets.count 导致应用在编译时崩溃,出现 EXC_BREAKPOINT 错误,控制台或 XCode UI 中没有错误描述(这让我更加困惑,因为我的代码中没有断点!).

results in the app not crashing anymore. Instead, however, I believe that line of code fails to do anything (which doesn't throw an error for some reason?) because attempting to print button.allTargets or even button.allTargets.count results in the app crashing at compile time, with an EXC_BREAKPOINT error and no error description in the console or the XCode UI (which just confuses me even more because there are no breakpoints in my code!).

此外,使 buttonPressed(_:) 非静态不会改变前面提到的任何观察结果.

Also, making buttonPressed(_:) non-static does not change any of the previously mentioned observations.

另外,为了确保按钮实际上可以交互,我在ControllerviewDidLoad()中添加了这个:

Also, to make sure the button could in fact be interacted with, I added this in the viewDidLoad() of Controller:

for subview in toolbar.subviews? {
    if let button = subview as? UIButton {
        button.addTarget(self, action: #selector(buttonPressed(_:)), for: .touchUpInside)
    }
}

并为按钮添加了一个简单的测试方法到Controller:

and added a simple testing method to Controller for the button:

@objc func buttonPressed(_ sender: UIButton) {
    print("Button Pressed")
}

并且运行代码确实会在控制台日志中打印Button Pressed",因此用户应该能够与该按钮进行交互.

And running the code did result in "Button Pressed" being printed in the console log, so the button should be able to be interacted with by the user.

如果您认为这些代码不足以解决问题,请随时告诉我,我会发布更多详细信息.

Feel free to let me know if you think this is not enough code to figure out the problem, and I will post more details.

编辑我更喜欢在 CustomToolbarWrapper 类中保留按钮操作的实现,以防止将来重复代码,因为无论 CustomToolbarWrapper 的实例在哪里,操作都是相同的已创建.

Edit I prefer to keep the implementation of the button's action in the CustomToolbarWrapper class to prevent repeating code in the future, since the action will be the same no matter where an instance of CustomToolbarWrapper is created.

推荐答案

最好的选择是在控制器中添加目标,然后在按下按钮时调用 toolbarWrapper 中的方法.但是如果你真的需要保持这个设计,你应该在你的控制器类中有一个对你的 toolbarWrapper 的强引用,否则你的 toolbarWrapper 被释放并且没有任何东西被调用.此外,buttonTapped(_:) 方法不需要是静态的.因此,在您的控制器中:

The best option would be to add the target in your controller and then call a method in your toolbarWrapper on button press. But if you really need to keep this design, you should have a strong reference to your toolbarWrapper in your controller class, otherwise your toolbarWrapper is deallocated and nothing gets called. Also, the buttonTapped(_:) method does not need to be static. Thus, in your controller:

class Controller: UIViewController {

    var toolbarWrapper: CustomToolbarWrapper?

    override func viewDidLoad() {
        toolbarWrapper = CustomToolbarWrapper(view: view, target: self)
        let toolbar = toolbarWrapper.toolbarView
        view.addSubview(toolbar)

        ... Other code ...

    }
}

在你的包装器中:

class CustomToolbarWrapper {

    var toolbarView: UIView

    init(view: UIView, target: Any) {
        let height: CGFloat = 80
        toolbarView = UIView(frame: CGRect(x: 0, y: view.frame.height - height,width: view.frame.width, height: height))
        let button = UIButton()

        ... Some button layout code ...

        button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
        toolbarView.addSubview(button)
    }

    @objc func buttonTapped(_ sender: Any) {
        print("button tapped")
    }
}

这篇关于如何向另一个类中的 UIButton 添加操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆