UIButton.addTarget 无法正常工作。似乎是一个时间问题?

Posted

技术标签:

【中文标题】UIButton.addTarget 无法正常工作。似乎是一个时间问题?【英文标题】:UIButton.addTarget not working correctly. Seems to be a timing thing? 【发布时间】:2018-08-02 16:35:13 【问题描述】:

我正在创建一个带有 2 个子视图的 ViewController。一个是用于我的主视图顶部的导航按钮,以及下方的浏览器窗口 (WKWebView)

在主视图控制器的 viewDidLoad 函数中,我创建这些视图并将其添加为子视图。然后我创建按钮并将其添加到导航视图。我以编程方式设置所有按钮的约束以手动定位它们并调整它们的大小。

-- 编辑--

我注意到在检查层次结构中的按钮时,目标已设置但操作为空。

Here is an image showing this

但是,当我在添加目标后立即检查断点上的操作时,它似乎确实存在。

This was done on a breakpoint immediately after adding the target


我添加目标如下

btnClose!.addTarget(self, action: #selector(onCloseClicked), for:UIControlEvents.touchUpInside)

点击事件不会触发。但是,如果我在该行之后放置一个断点,并在控制台中通过

查看按钮的操作
po btnClose!.allTargets

然后它向我显示目标,然后在继续执行时按钮工作正常。我认为结果是某种时间问题,但我不确定问题是什么。

我使用的是 Swift 4.1。

-- 编辑--

这是该按钮中涉及的所有代码:(我删除了所有不相关的 webview 代码)

public func initialize() // called by viewDidLoad
    navigationView = UIView(frame:navigationRect)
    navigationView!.isOpaque = true
    navigationView!.isUserInteractionEnabled = true
    navigationView!.backgroundColor = UIColor(red: 58.0/255.0, green: 60.0/255.0, blue: 67.0/255.0, alpha: 1)
    view.addSubview(navigationView!)
    addNavigationButtons()

private func addNavigationButtons()
    btnClose = UIButton()
    btnClose!.addTarget(self, action: #selector(onCloseClicked), for:UIControlEvents.touchUpInside)

    btnClose!.frame = btnRect // x:0, y:0, width:50, height:50

    btnClose?.translatesAutoresizingMaskIntoConstraints = false
    btnClose!.setImage(UIImage(named: "navigationClose", in: Bundle(identifier:"myframework"), compatibleWith:nil), for:UIControlState.normal)

    navigationView!.addSubview(btnClose!)

    addButtonConstraints()


private func addButtonConstraints()
    // close
    navigationView!.addConstraint(NSLayoutConstraint(item:navigationView!, attribute: .right, relatedBy: .equal, toItem: btnClose!, attribute: .right, multiplier:1.0, constant:0))
    navigationView!.addConstraint(NSLayoutConstraint(item:navigationView!, attribute: .centerY, relatedBy: .equal, toItem: btnClose!, attribute: .centerY, multiplier:1.0, constant:0))
    btnClose!.addConstraint(NSLayoutConstraint(item:btnClose!, attribute: .width, relatedBy:.equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant:MRAIDBrowserWindow.btnWidth)) //btnWidth = 50
    btnClose!.addConstraint(NSLayoutConstraint(item:btnClose!, attribute: .height, relatedBy:.equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant:MRAIDBrowserWindow.btnHeight)) //btnHeight = 50


@objc public func onCloseClicked() // tried this without @objc
    print("this doesn't work, unless I have a breakpoint stoppage")

【问题讨论】:

把你的viewDidLoad代码和按钮创建和按钮操作方法。 好的,我做到了,谢谢 像这样创建按钮 ;-> var button: UIButton = UIButton(type: .Custom) button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0) button.addTarget(self, action: #selector(self.onCloseClicked), forControlEvents: .TouchUpInside) 感谢 vivekDas,但这在这个版本的 swift 中不起作用。 你有哪个版本? 【参考方案1】:

首先我应该告诉你,我不擅长以编程方式设置约束,所以我不能给你一个合理的建议。

这是我所做的,我正在分享你自己的工作代码,只有一些更改......

    我已将自己的图像名称和背景颜色添加到按钮以查看某些组件可能会影响按钮 我已经删除了在 btnClose! 上设置的框架,因为我注意到当你告诉容器的所有边约束时,你不需要告诉框架。

你应该再看看它,下面是我编译检查的代码 -> 你的操作方法调用正常

导入 UIKit

类 MyTestActionViewController: UIViewController

var navigationView : UIView?
var btnClose : UIButton?

override func viewDidLoad() 
    super.viewDidLoad()
    
    self.initialize()


public func initialize() // called by viewDidLoad
    navigationView = UIView(frame:CGRect(x:5, y:55, width:200, height:200))
    navigationView!.isOpaque = true
    navigationView!.isUserInteractionEnabled = true
    navigationView!.backgroundColor = UIColor(red: 58.0/255.0, green: 60.0/255.0, blue: 67.0/255.0, alpha: 1)
    view.addSubview(navigationView!)
    addNavigationButtons()

private func addNavigationButtons()
    btnClose = UIButton()
    btnClose!.addTarget(self, action: #selector(onCloseClicked), for:UIControlEvents.touchUpInside)
    
    btnClose?.backgroundColor = UIColor.red
    btnClose?.translatesAutoresizingMaskIntoConstraints = false
    btnClose?.setImage(UIImage(named: "myButtonImage"), for:UIControlState.normal)
    navigationView?.addSubview(btnClose!)
    
    addButtonConstraints()


private func addButtonConstraints()
    // close
    navigationView!.addConstraint(NSLayoutConstraint(item:navigationView!, attribute: .right, relatedBy: .equal, toItem: btnClose!, attribute: .right, multiplier:1.0, constant:0))
    navigationView!.addConstraint(NSLayoutConstraint(item:navigationView!, attribute: .centerY, relatedBy: .equal, toItem: btnClose!, attribute: .centerY, multiplier:1.0, constant:0))
    btnClose!.addConstraint(NSLayoutConstraint(item:btnClose!, attribute: .width, relatedBy:.equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant:50)) //btnWidth = 50
    btnClose!.addConstraint(NSLayoutConstraint(item:btnClose!, attribute: .height, relatedBy:.equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant:50)) //btnHeight = 50


@objc public func onCloseClicked() // tried this without @objc
    print("this doesn't work, unless I have a breakpoint stoppage")

一张图片显示 -> 你的按钮动作正确

【讨论】:

感谢您为我测试这个。但是,这只是确认代码不是问题。层次结构中的视图控制器之间一定会发生某种冲突吗?有这个问题的视图控制器在所有其他视图控制器之上,但下面有一个视图控制器。这会导致问题吗?我尝试在下部视图控制器中禁用用户交互,但没有帮助。 在我了解所有细节之前,我无法确定。顺便说一句,层次结构不应该干扰独立控制器的功能,直到它不是使用 (addChildViewController:) 添加的另一个 viewController 的子部分,你能分享你的项目,以便人们可以看到影响功能的所有方面吗?共享您的公共项目 git 存储库链接或您可以选择的其他一些工作选项??【参考方案2】:

在方法addNavigationButtons中,放入以下行

btnClose!.addTarget(self, action: #selector(onCloseClicked), for:UIControlEvents.touchUpInside)

之后

navigationView!.addSubview(btnClose!)

我认为新版本的 swift 有一个限制,如果按钮不在 ui 视图层次结构中,并且您尝试在其上添加目标操作,它实际上不会起作用。因此,请确保先将按钮添加到 ui 视图层次结构中。

【讨论】:

以上是关于UIButton.addTarget 无法正常工作。似乎是一个时间问题?的主要内容,如果未能解决你的问题,请参考以下文章

iPhone UIButton addTarget:action:forControlEvents: 不工作

UIButton addTarget 不适用于 iOS7,但适用于 IOS6

具有自定义视图的 UIButton - addTarget:action:forControlEvents: 不起作用

UIButton addTarget 与 UIViewCollectionView 内的参数

UIButton addTarget 在不同的 ViewController

UIButton addTarget 到另一个类的方法