I have a UIView which is added as a subview to my view controller. I have drawn a bezier path on that view. My drawRect implementation is below
- (void)drawR
A solution in Swift 3.1 (porting over the Apple recommended solution from here)
func containsPoint(_ point: CGPoint, path: UIBezierPath, inFillArea: Bool) -> Bool {
UIGraphicsBeginImageContext(self.size)
let context: CGContext? = UIGraphicsGetCurrentContext()
let pathToTest = path.cgPath
var isHit = false
var mode: CGPathDrawingMode = CGPathDrawingMode.stroke
if inFillArea {
// check if UIBezierPath uses EO fill
if path.usesEvenOddFillRule {
mode = CGPathDrawingMode.eoFill
} else {
mode = CGPathDrawingMode.fill
}
} // else mode == stroke
context?.saveGState()
context?.addPath(pathToTest)
isHit = (context?.pathContains(point, mode: mode))!
context?.restoreGState()
return isHit
}
Detecting tap inside a bezier path in swift :-
It's simple in latest swift ,follow these steps and you will get your UIBezierPath touch event.
Step 1 :- Initialize Tap Event on view where your UIBeizerPath Added.
///Catch layer by tap detection
let tapRecognizer:UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(YourClass.tapDetected(_:)))
viewSlices.addGestureRecognizer(tapRecognizer)
Step 2 :- Make "tapDetected" method
//MARK:- Hit TAP
public func tapDetected(tapRecognizer:UITapGestureRecognizer){
let tapLocation:CGPoint = tapRecognizer.locationInView(viewSlices)
self.hitTest(CGPointMake(tapLocation.x, tapLocation.y))
}
Step 3 :- Make "hitTest" final method
public func hitTest(tapLocation:CGPoint){
let path:UIBezierPath = yourPath
if path.containsPoint(tapLocation){
//tap detected do what ever you want ..;)
}else{
//ooops you taped on other position in view
}
}
Update: Swift 4
Step 1 :- Initialize Tap Event on view where your UIBeizerPath Added.
///Catch layer by tap detection
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(YourClass.tapDetected(tapRecognizer:)))
viewSlices.addGestureRecognizer(tapRecognizer)
Step 2 :- Make "tapDetected" method
public func tapDetected(tapRecognizer:UITapGestureRecognizer){
let tapLocation:CGPoint = tapRecognizer.location(in: viewSlices)
self.hitTest(tapLocation: CGPoint(x: tapLocation.x, y: tapLocation.y))
}
Step 3 :- Make "hitTest" final method
private func hitTest(tapLocation:CGPoint){
let path:UIBezierPath = yourPath
if path.contains(tapLocation){
//tap detected do what ever you want ..;)
}else{
//ooops you taped on other position in view
}
}
There is a function CGPathContainsPoint()
it may be useful in your case.
Also be careful if you get gesture point from superview, the coordinate may not be correct with your test. You have a method to convertPoint from or to a particular view's coordinate system:
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view
Try UIBezierPath's method :
func contains(_ point: CGPoint) -> Bool
Returns a Boolean value indicating whether the area enclosed by the receiver contains the specified point.