Search code examples
swiftuibuttonaddtarget

Custom Button Not Working in Swift


I have a UIViewController, a Custum UIView, and a GameController. The CustumUiView is layered on top of the UIViewController and I need to seperate out the views to track clicks on the UIView. I have a custom button in the Custum UIView "Interface View" that is registering the click, but the receiver in the GameController or the UIViewController (tried both) are not registering the clicks.

Code follows and help is appreciated.

Interface View

class InterfaceView: UIView {

var resetButton: UIButton!

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    resetButton = UIButton(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
    resetButton.setImage(UIImage(named: "reset"), for: UIControlState())
    addSubview(resetButton)
}

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    // let touches through and only catch the ones on buttons
    let hitView = super.hitTest(point, with: event)

    if hitView is UIButton {
        print("Captured Hit") // Stack Overflow Note: This is working.
        return hitView
    }

    return nil
}
}

Game Controller:

class GameController
{
    var interface: InterfaceView!
    {
        didSet
        {
            interface.resetButton.addTarget(self, action: #selector (GameController.reset), for: .touchUpInside)
        }

    @objc func reset(sender: UIButton!)
    {
        print("button pressed")
    }
}

UIViewController:

class GameViewController: UIViewController
{

fileprivate let controller: GameController
@IBOutlet weak var GameView: UIView!

init(_ coder: NSCoder? = nil)
{
    // Logic Goes Here
    controller = GameController()

    if let coder = coder
    {
        super.init(coder: coder)!
    } else
    {
        super.init(nibName: nil, bundle: nil)
    }
}

required convenience init(coder: NSCoder)
{
    self.init(coder)
}
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
{
    if let touch = touches.first as UITouch?
    {
        let point = touch.preciseLocation(in: GameView)
        if (touch.view == GameView)
        {
           print("Do stuff")
        }
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?)
{
    if let touch = touches.first
    {
        let point = touch.preciseLocation(in: GameView)
        if (touch.view == GameView)
        {
            print("Do other stuff")
        }
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?)
{
    print("Reset Stuff")
}

Solution

  • Resolved by in GameViewController, using didSet to set the target and selector for the button press and then using a method in GameViewController to call a method within GameController.

    @IBOutlet weak var interface: InterfaceView!
    {
        didSet
        {
            interface.resetButton.addTarget(self, action: #selector (GameViewController.reset), for: .touchUpInside)
        }
    }