不会调用程序化UIButton操作

时间:2018-08-24 09:50:37

标签: ios swift uibutton

我创建了一个类,该类将创建/管理多个按钮和标签,并将它们添加到视图中,但是我无法从按钮中获取要触发的操作。

这是简单的代码版本,但没有可以正常运行的“ MakerClass”(代码在主ViewController中):

@objc func pressed(_ sender: UIButton!) {
    print("pressed")
}
    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.


    let backgroundButton = UIButton()
    backgroundButton.backgroundColor = UIColor.green
    backgroundButton.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
    self.view.addSubview(backgroundButton)

    backgroundButton.addTarget(self, action: #selector(pressed(_:)), for: .touchUpInside)

}

这是一个版本,其中我将按钮的创建放到另一个类中

ViewController

    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.


    MakerClass(intoView: self.view)                
}

MakerClass

class MakerClass {


    var backgroundButton: UIButton = UIButton()


    @objc func iwastouched(_ sender: UIButton!) {
        print("touched")
    }

    init(intoView: UIView){

        backgroundButton.backgroundColor = UIColor.red
        backgroundButton.frame = CGRect(x: 0, y: 200, width: 100, height: 100)
        intoView.addSubview(backgroundButton)
        backgroundButton.addTarget(self, action: #selector(iwastouched(_:)), for: .touchUpInside)

    }


}

我一直在使用的项目可以从here

下载

由于我是iOS编程的新手,我可能会采用错误的方式

1 个答案:

答案 0 :(得分:1)

问题在于,由于您没有保留MakerClass,因此按钮的目标设置为NSNull()

您可以通过添加…来看到它

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    let buttons = view.subviews as! [UIButton]
    for button in buttons {

        print(button)
        print("Target :", button.allTargets.first!)
    }
}
<UIButton: 0x7ff89fd04110; frame = (0 0; 100 100); opaque = NO; layer = <CALayer: 0x60000257bac0>>
Target : <TestProgrammaticButton.ViewController: 0x7ff89ff08050>
<UIButton: 0x7ff89fd05020; frame = (0 200; 100 100); opaque = NO; layer = <CALayer: 0x60000257bb40>>
Target : <null>

如果您希望按钮在视图控制器中触发操作方法,则可以...

class MakerClass {
    init(intoView: UIView, with viewController: ViewController) {
        // configure
        backgroundButton.addTarget(viewController, action: #selector(iwastouched(_:)), for: .touchUpInside)
    }
}

但这将您的MakerClass与特定的ViewController类联系起来。

相反,您的MakerClass可以返回格式化的按钮,然后在视图控制器中设置目标/操作。


更新

根据@RakeshaShastri在下面的评论,由于将目标设置为NSNull(),应用程序将沿着响应者链上行,寻找UIResponder(通常是UIView或{{1} })具有正确的func签名。您的情况下的响应者链是……

UIViewController-> backgroundButton-> ViewController.view-> ViewController

您还可以通过添加

进行测试
UIWindow

进入您的@objc func iwastouched(_ sender: UIButton!) { print("touched") } 班。