我会尽量简短。
接受以下测试代码:
CGPath* path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, 318.43, 183.47);
CGPathAddCurveToPoint(path, nil, 322.98, 189.32, 327, 194.93, 329.81, 201.62);
CGPathAddLineToPoint(path, nil, 339.36, 182.58);
CGPathCloseSubpath(path);
CGPathMoveToPoint(path, nil, 327.8, 193.04);
CGPathAddCurveToPoint(path, nil, 323.06, 193.04, 323.06, 185.5, 327.8, 185.5);
CGPathAddCurveToPoint(path, nil, 332.54, 185.5, 332.54, 193.04, 327.8, 193.04);
CGPathCloseSubpath(path);
CGRect boundingBox = CGPathGetBoundingBox(path);
CGPoint testPoint = CGPointMake(200,185);
NSLog(@"path contains point=%d | bounding box contains point=%d",CGPathContainsPoint(path, nil, testPoint, NO), CGRectContainsPoint(boundingBox, testPoint) );
此代码在iOS 10上正确返回:
路径包含点= 0 |边界框包含point = 0
iOS 12上的相同代码返回:
路径包含point = 1 |边界框包含point = 0
如您所见,在iOS 12上CGPathContainsPoint表示我的testPoint在该形状内,即使该形状的边界框没有显示。
在CGPathContainsPoint中将填充规则更改为NO不会更改任何内容。
有解决方案吗? 我之前尝试过苹果论坛,但似乎没人回答。
谢谢您的帮助!
答案 0 :(得分:2)
在与iOS 10.3和12.1相同的模拟器上确认了此问题
我不明白为什么会这样,唯一的线索是如果我们删除此行,问题就会消失
CGPathMoveToPoint(path, nil, 327.8, 193.04);
CGPathAddCurveToPoint(path, nil, 323.06, 193.04, 323.06, 185.5, 327.8, 185.5);
CGPathAddCurveToPoint(path, nil, 332.54, 185.5, 332.54, 193.04, 327.8, 193.04);
CGPathCloseSubpath(path);
这可能是由于填充规则或其他原因(例如,由于路径重叠)引起的,无论如何,解决方法是创建单独的路径,然后按如下方式合并其边界框(添加了一些绘图代码以使事物可视化)
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGPoint testPoint = CGPointMake(200,185);
[[UIColor blueColor] setStroke];
CGContextStrokeEllipseInRect(context, CGRectMake(testPoint.x - 5, testPoint.y - 5, 10, 10));
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, 318.43, 183.47);
CGPathAddCurveToPoint(path, nil, 322.98, 189.32, 327, 194.93, 329.81, 201.62);
CGPathAddLineToPoint(path, nil, 339.36, 182.58);
CGRect box1 = CGPathGetBoundingBox(path);
NSLog(@"path 1 contains point=%d | bounding box contains point=%d", CGPathContainsPoint(path, nil, testPoint, NO), CGRectContainsPoint(box1, testPoint));
[[UIColor grayColor] setFill];
[[UIColor redColor] setStroke];
CGContextAddPath(context, path);
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);
CGPathRelease(path);
path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, 327.8, 193.04);
CGPathAddCurveToPoint(path, nil, 323.06, 193.04, 323.06, 185.5, 327.8, 185.5);
CGPathAddCurveToPoint(path, nil, 332.54, 185.5, 332.54, 193.04, 327.8, 193.04);
CGRect box2 = CGPathGetBoundingBox(path);
NSLog(@"path 2 contains point=%d | bounding box contains point=%d", CGPathContainsPoint(path, nil, testPoint, NO), CGRectContainsPoint(box2, testPoint));
[[UIColor yellowColor] setFill];
[[UIColor greenColor] setStroke];
CGContextAddPath(context, path);
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);
CGPathRelease(path);
CGRect boundingBox = CGRectUnion(box1, box2);
[[UIColor magentaColor] setStroke];
CGContextStrokeRect(context, boundingBox);
NSLog(@"bounding box contains point=%d", CGRectContainsPoint(boundingBox, testPoint));
}
答案 1 :(得分:1)
我看到了您描述的相同行为。有趣的是,如果您手动关闭路径,它似乎可以工作。例如,除了添加带有注释的行之外,这与您的路径相同:
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, 318.43, 183.47);
CGPathAddCurveToPoint(path, nil, 322.98, 189.32, 327, 194.93, 329.81, 201.62);
CGPathAddLineToPoint(path, nil, 339.36, 182.58);
CGPathAddLineToPoint(path, nil, 318.43, 183.47); // manually add line back to starting point
CGPathCloseSubpath(path);
CGPathMoveToPoint(path, nil, 327.8, 193.04);
CGPathAddCurveToPoint(path, nil, 323.06, 193.04, 323.06, 185.5, 327.8, 185.5);
CGPathAddCurveToPoint(path, nil, 332.54, 185.5, 332.54, 193.04, 327.8, 193.04);
CGPathCloseSubpath(path);
我可能建议尝试自己跟踪起点,并在关闭子路径的任何地方添加一条回线,看看是否能解决该问题。
更莫名其妙的是,两次CGPathMoveToPoint
(大声笑)似乎也可以解决。
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, 318.43, 183.47);
CGPathMoveToPoint(path, nil, 318.43, 183.47); // move the the starting point twice?!?
CGPathAddCurveToPoint(path, nil, 322.98, 189.32, 327, 194.93, 329.81, 201.62);
CGPathAddLineToPoint(path, nil, 339.36, 182.58);
CGPathCloseSubpath(path);
CGPathMoveToPoint(path, nil, 327.8, 193.04);
CGPathAddCurveToPoint(path, nil, 323.06, 193.04, 323.06, 185.5, 327.8, 185.5);
CGPathAddCurveToPoint(path, nil, 332.54, 185.5, 332.54, 193.04, 327.8, 193.04);
CGPathCloseSubpath(path);