从另一个类触摸时的 Swift 按钮操作选择器:无法识别的选择器发送到实例

Posted

技术标签:

【中文标题】从另一个类触摸时的 Swift 按钮操作选择器:无法识别的选择器发送到实例【英文标题】:Swift button action selector when touched from another class: unrecognized selector sent to instance 【发布时间】:2018-09-19 11:03:02 【问题描述】:

在 UIViewController(下面是我的 BaseViewController)中,我添加了一个包含按钮的弹出对话框视图(来自另一个类 NotifDialog)的子视图。

触摸此按钮时应隐藏弹出对话框。

我的问题是按钮没有检测到触摸或抛出“无法识别的选择器发送到实例”

class NotifDialog: NSObject 
    var dialogView: UIView!

    superView = controller.view
    dialogView = UIView()        

    superView?.addSubview(dialogView)
    dialogView.translatesAutoresizingMaskIntoConstraints = false

    let dialogViewWidth = BaseViewController.screenWidth * 0.66
    let dialogViewHeight = BaseViewController.screenHeight * 0.45

    dialogView.centerXAnchor.constraint(equalTo: (superView?.safeAreaLayoutGuide.centerXAnchor)!).isActive = true
    dialogView.centerYAnchor.constraint(equalTo: (superView?.safeAreaLayoutGuide.centerYAnchor)!).isActive = true
    dialogView.widthAnchor.constraint(equalToConstant: dialogViewWidth).isActive = true
    dialogView.heightAnchor.constraint(equalToConstant: dialogViewHeight).isActive = true        

    let bClose = UIButton()

    dialogView?.addSubview(bClose)

    bClose.translatesAutoresizingMaskIntoConstraints = false

    let bCloseWidth = dialogViewWidth * 0.5

    bClose.centerXAnchor.constraint(equalTo: dialogView.safeAreaLayoutGuide.centerXAnchor).isActive = true
    bClose.topAnchor.constraint(equalTo: dialogView.topAnchor, constant: 25).isActive = true
    bClose.widthAnchor.constraint(equalToConstant: bCloseWidth).isActive = true
    bClose.heightAnchor.constraint(equalToConstant: 25).isActive = true

    //bClose.addTarget(controller, action:#selector(self.hide(_:)), for: .touchUpInside) -> touch not detected
    //bClose.addTarget(self, action:#selector(self.closeDialog(_:)), for: .touchUpInside) -> throws error "unrecognized selector sent to instance"



func closeDialog(_ sender : UIButton) 
    dialogView.isHidden = true

.

class BaseViewController: UIViewController 

override func viewDidLoad() 
    super.viewDidLoad()
    let topViewController :UIViewController = self.navigationController!.topViewController!
    let dialog = NotifDialog()
    dialog.loadCustomViewIntoController(controller: topViewController)

按以下方式设置我的按钮使其就像未检测到触摸

bClose.addTarget(self, action:#selector(closeDialog(_:)), for: .touchUpInside)

按以下方式设置我的按钮会检测到触摸,但会引发错误:“无法识别的选择器已发送到实例”

bClose.addTarget(controller, action:#selector(closeDialog(_:)), for: .touchUpInside)

最后,我还尝试将函数 closeDialog 设为静态。在这种情况下,它不再崩溃,但是我不能在其中使用 dialogView,因为这个 var 不是静态的。

如何在这个按钮的触摸下隐藏我的对话框?

【问题讨论】:

【参考方案1】:

closeDialog 消息被发送到您在addTarget 调用中指定的目标。由于 NotifDialog 类中存在closeDialog 方法,因此您需要将 NotifDialog 实例设为目标。

bClose.addTarget(
    dialog, // This is the instance that will receive the message
    action:#selector(closeDialog(_:)),
    for: .touchUpInside
)

【讨论】:

感谢您的帮助@Rengers。我熟悉在 A 类中创建 B 类的实例,但我真的不知道如何在 A 类中创建 A 类的实例。抱歉,如果这没有意义 问题可能是当viewDidLoad 返回时NotifDialog 的实例从内存中释放。尝试使dialog 成为BaseViewController 上的实例变量。 已经是这样了,我正在BaseViewController里面创建一个NotifDialog的实例。 是的,但您没有将其分配给实例变量。 dialog 变量的作用域是 viewDidLoad 方法,当该方法返回时会从内存中释放。 确实!将 NotifDialog 实例分配为 BaseViewController 的类 var 最终按预期工作,但它没有作为临时变量工作。谢谢@Rengers

以上是关于从另一个类触摸时的 Swift 按钮操作选择器:无法识别的选择器发送到实例的主要内容,如果未能解决你的问题,请参考以下文章

swift 实践- 04 -- UIButton

Swift - 按钮(UIButton)的用法

Swift:如何从另一个类 X 更新 UILabel:UIButton

Swift:从另一个类调用 UIButton press

从另一个类 Swift 更新视图控制器的 UI [关闭]

从另一个类Swift调用一个类的函数