UIBezierPath appending overlapping isn't filled
You were on the right track with setting the usesEvenOddFillRule
to false. In addition to that, you need to make sure your shapes are both drawn in the same direction (clockwise or counter-clockwise).
I reversed the order of your addLine
s when drawing the triangle to reverse it.
override func draw(_ rect: CGRect) {
let firstShape = UIBezierPath()
firstShape.move(to: CGPoint(x: 100, y: 100))
firstShape.addLine(to: CGPoint(x: 150, y: 170))
firstShape.addLine(to: CGPoint(x: 100, y: 150))
firstShape.close()
let secondShape = UIBezierPath(rect: CGRect(x: 125, y: 125, width: 75, height: 75))
let combined = UIBezierPath()
combined.append(firstShape)
combined.append(secondShape)
combined.usesEvenOddFillRule = false
UIColor.black.setFill()
combined.fill()
}
Union UIBezierPaths rather than apend path
Finally a solution!!
Using https://github.com/adamwulf/ClippingBezier you can find the intersecting points. Then you can walk through the path, turning left if clockwise or vice-versa to stay on the outside. Then you can generate a new path using the sequence of points.
Two UIBezierPaths intersection as a UIBezierPath
I wrote a UIBezierPath library that will let you cut a given closed path into sub shapes based on an intersecting path. It'll do essentially exactly what you're looking for: https://github.com/adamwulf/ClippingBezier
NSArray<UIBezierPath*>* componentShapes = [shapePath uniqueShapesCreatedFromSlicingWithUnclosedPath:scissorPath];
Alternatively, you can also just find the intersection points:
NSArray* intersections = [scissorPath findIntersectionsWithClosedPath:shapePath andBeginsInside:nil];
UIBezierPath not cleared on redraw
I think the problem is merely that your drawing is huge and strays outside the cell because your views do not clip to bounds. That's incoherent. Each cell needs to draw just its own content.
In other words, the overlapping you are seeing has nothing to do with the custom view drawing; it has to do with the cell drawing. You are infecting the neighboring cells with your drawing.
By the way, you say:
but this isn't at all ideal since I lose the background (it becomes black)."
You can fix that by saying self.backgroundColor = .clear
in your init
.
reuse UIBezierPath object
Give this a try:
UIBezierPath *bgPath = [UIBezierPath bezierPath];
UIColor *color = [UIColor colorWithHex:BG_ARC_COLOR];
[color set];
[bgPath addArcWithCenter:self.center radius:BG_RADIUS startAngle:START_ANGLE endAngle:END_ENGLE clockwise:ANTY_CLOCK_WISE];
bgPath.lineWidth = BG_ARC_WIDTH;
bgPath.lineCapStyle = kCGLineCapRound;
bgPath.lineJoinStyle = kCGLineCapRound;
[bgPath stroke];
[bgPath removeAllPoints];
[bgPath moveToPoint:self.center];
[bgPath addArcWithCenter:self.center radius:BG_CIRCYLE_RADIUS startAngle:0 endAngle:2 * M_PI clockwise:CLOCK_WISE];
[bgPath addLineToPoint:self.center];
[bgPath fill];
iOS - Clipping union of two paths using UIBezierPath appendPath
You can add back the piece that gets knocked out by the intersection using CGRectIntersection
CGContextSaveGState(context);
CGRect rect1 = CGRectMake(centrePoint.x - 2.0f, 0.0f, 4.0f, self.sizeY);
CGRect rect2 = CGRectMake(0.0f, centrePoint.y - 2.0f, self.sizeX, 4.0f);
CGRect rect3 = CGRectIntersection(rect1, rect2);
CGContextAddRect(context, rect1);
CGContextAddRect(context, rect2);
CGContextAddRect(context, rect3);
CGRect boundingRect = CGContextGetClipBoundingBox(context);
CGContextAddRect(context, boundingRect);
CGContextEOClip(context);
// draw the icon shape (clipped portion is removed)
iconBezierPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(self.sizeX / 3.0f, self.sizeY / 2.25f, self.sizeX / 3.0f, self.sizeX / 3.0f)];
[highlightColor setFill];
[iconBezierPath fill];
CGContextRestoreGState(context);
This satisfies the requirements of your question, but whether it entirely satisfies your needs depends on the nature of the "other overlapping paths".
Related Topics
Playing Hls (M3U8) in Cocoa Os X Avplayer - Swift
Swift 3 Type Inference Confusion
Treat a Single Integer Value as a Range in Swift
Core Data with Pre-Filled .Sqlite (Swift3)
Big O of Accessing a String with an Index in Swift 3.0
Xcode - Build Setting "Excluded_Source_File_Names" Not Working
How to Set Alignment for Wkinterface Label Using Setattributedtext
Swift: Reduce Function with a Closure
How to Initialize a Unichar Variable in Swift
Swiftui Sheet Gets Dismissed the First Time It Is Presented
Hex String to Text Conversion - Swift 3
Swift Generics Protocols: Can Only Be Used as a Generic Constraint Problem
Adopting Customnserror in Decodingerror
Realmswift Initialize List:Cannot Specialize a Non-Generic Definition
Xcode Generated Coredata Files Cannot Be Processed by Copy Bundle Resources Build Phase
Why Are Objects in the Same Sknode Layer Not Interacting with Each Other