Detecting a tap on a CAShapeLayer in Swift?

John picture John · Apr 21, 2015 · Viewed 10.3k times · Source

I'm quite new to iOS Development (so please forgive my ineptitude - I've looked everywhere!), and was looking to find a way to detect a tap on a CAShapeLayer. So far, I've come across hitTest. Is hitTest the best method, and if so how is it used in Swift especially with CAShapeLayers? Also, if I had numerous CAShapeLayers, how would I use the hitTest method to refer to them individually?

This is how I created the CAShapeLayer:

    let newBounds = CGRect(x: 0, y: 0, width: 200, height: 200)
    let newShape = CAShapeLayer()
    newShape.bounds = newBounds
    newShape.position = view.center
    newShape.cornerRadius = newBounds.width / 2
    newShape.path = UIBezierPath(ovalInRect: newShape.bounds).CGPath

    newShape.lineWidth = 42
    newShape.strokeColor = UIColor(red: 222/255.0, green: 171/255.0, blue: 66/255.0, alpha: 1.0).CGColor
    newShape.fillColor = UIColor.clearColor().CGColor

    newShape.strokeStart = 0.2
    newShape.strokeEnd = 0.4

    view.layer.addSublayer(newShape)

Answer

Arbitur picture Arbitur · Apr 21, 2015

Heres imo the best way to do what you want to achieve:

// First add the shapelayer
let layer = CAShapeLayer()
layer.anchorPoint = CGPointZero
layer.path = UIBezierPath(ovalInRect: CGRect(x: 0, y: 0, width: 100, height: 200)).CGPath
layer.bounds = CGPathGetBoundingBox(layer.path) // IMPORTANT, without this hitTest wont work
layer.fillColor = UIColor.redColor().CGColor
self.view.layer.addSublayer(layer)


// Check for touches
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    let point = touches.anyObject()!.locationInView(self.view) // Where you pressed

    if let layer = self.view.layer.hitTest(point) as? CAShapeLayer { // If you hit a layer and if its a Shapelayer
        if CGPathContainsPoint(layer.path, nil, point, false) { // Optional, if you are inside its content path
            println("Hit shapeLayer") // Do something
        }
    }
}