Touch Detection on CAShapeLayer in Swift?

I am new to iOS development (so please forgive my ineptitude - I searched everywhere!) And searched for a way to detect CAShapeLayer touch. So far I have come across hitTest . Is hitTest best method, and if so, how is it used in Swift, especially with CAShapeLayer s? Also, if I had a lot of CAShapeLayers , how would I use the hitTest method to reference them individually?

This is how I created 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) 
+6
source share
4 answers

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 } } } 
+9
source

Swift 4 ,

My UIImageView has several CAShapeLayer objects, this is how I was able to detect touches on them.

 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { let touch = touches.first guard let point = touch?.location(in: imageView) else { return } guard let sublayers = imageView.layer.sublayers as? [CAShapeLayer] else { return } for layer in sublayers{ if let path = layer.path, path.contains(point) { print(layer) } } } 

link

+6
source

I used the Arbitur code and I had some errors. Here is the code that I had without errors. For quick 3.2 / 4.0

 override func viewDidLoad() { super.viewDidLoad() let layer = CAShapeLayer() layer.anchorPoint = CGPoint.zero layer.path = UIBezierPath.init(ovalIn: CGRect(x: 0, y: 0, width: 100, height: 200)).cgPath layer.bounds = (layer.path?.boundingBox)! // IMPORTANT, without this hitTest wont work layer.fillColor = UIColor.red.cgColor self.view.layer.addSublayer(layer) } // Check for touches override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { let point = touches.first?.location(in: 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 (layer.path?.contains(point!))! { // Optional, if you are inside its content path print("Hit shapeLayer") // Do something } } } 
+2
source

Use the following code to get a touch of CAShapeLayer .

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { for (UITouch *touch in touches) { CGPoint touchLocation = [touch locationInView:self.view]; for (id sublayer in self.view.layer.sublayers) { BOOL touchInLayer = NO; if ([sublayer isKindOfClass:[CAShapeLayer class]]) { CAShapeLayer *shapeLayer = sublayer; if (CGPathContainsPoint(shapeLayer.path, 0, touchLocation, YES)) { // Here your code for do any opration. touchInLayer = YES; } } else { CALayer *layer = sublayer; if (CGRectContainsPoint(layer.frame, touchLocation)) { // Touch is in this rectangular layer touchInLayer = YES; } } } } } 
0
source

All Articles