Search code examples
iosswiftuiviewuiviewcontrollertouchesbegan

touchesBegan and touchesMoved not getting triggered on UIView


What I'm trying to achieve:

Trying to grab the coordinate of the currently touched area on the screen and draw the received coordinate on the screen. Simply put, a basic drawing app that's all written programmatically (for my own practice).

Problem

touchesBegan and touchesMoved for PaintingSubclass are not getting called at all.

Current setup

  • I have a PaintingViewController then I also have a PaintingSubclass.

  • PaintingViewController is a UIViewController and PaintingSubclass is a UIView.

  • PaintingViewController creates an instance of PaintingSubclass and adds it to the subview of PaintingViewController.

  • PaintingSubclass is where the actual drawing happens.

What I've tried so far

  • Put a breakpoint inside the touchesMoved and touchesBegan (didn't work)
  • Tried to add a UITapGestureRecognizer (didn't work)
  • Enabled self.isUserInteractionEnabled = true (didn't work)
  • Make PaintingSubclass inherit UIControl and call sendActions(for: .valueChanged) at the end of touchesMoved and touchesBegan (didn't work)

Current Code

(please ignore any the unnecessary variables)

import UIKit

class PaintingViewController: UIViewController{

var _paintView: PaintingSubclass? = nil

override func loadView() {
    view = UILabel()
}

private var labelView: UILabel {
    return view as! UILabel
}

override func viewDidLoad() {

    _paintView = PaintingSubclass()
    _paintView?.frame = CGRect(x: view.bounds.minX, y: view.bounds.minY, width: 400, height: 750)
    _paintView?.backgroundColor = UIColor.white
    _paintView?.setNeedsDisplay()

    view.addSubview(_paintView!)
}

class PaintingSubclass: UIView{

    private var context: CGContext? = nil
    var styleSelection: String = "buttcap"
    var linewidth: Float = 5
    var lineCapStyle: CGLineCap? = nil
    var lineJoinStyle: CGLineJoin? = nil
    var lineWidthValue: CGFloat? = nil
    var colorValue: UIColor? = nil

    override init(frame: CGRect) {
        super.init(frame: frame)
        lineWidthValue = 0.5
        colorValue = UIColor(cgColor: UIColor.black.cgColor)
        self.isUserInteractionEnabled = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func draw(_ rect: CGRect) {

        context = UIGraphicsGetCurrentContext()!
        context?.move(to: CGPoint(x: 0.0, y: 110.0))
        context?.setStrokeColor((colorValue?.cgColor)!)
        context?.drawPath(using: CGPathDrawingMode.stroke)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        let touch: UITouch = touches.first!
        let touchPoint: CGPoint = touch.location(in: self)

        let _xValue = touchPoint.x
        let _yValue = touchPoint.y

        NSLog("coordinate: \(_xValue), \(_yValue)")
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)

        let touch: UITouch = touches.first!
        let touchPoint: CGPoint = touch.location(in: self)

        let _xValue = touchPoint.x
        let _yValue = touchPoint.y

        NSLog("coordinate: \(_xValue), \(_yValue)")
    }   
}
}

What am I doing wrong here? Been stuck in this state for hours not making any progress. Any help/feedbacks will be much appreciated.


Solution

  • I don't know why you are setting your default view to UILabel(), but your default isUserInteractionEnabled of your view is false. Set it to true

    override func loadView() {
        view = UILabel()
        view.isUserInteractionEnabled = true
    }