Reputation: 1915
Ok, I've an array of dummy objects containing property cgpath. This is called darkPathArray property in my UIView.
When I draw them one after another I found an interesting thing to happen. I got EXC_BAD_ACCESS on CGContextAddPath(context,ppath.path);
(ppath.path
throws that) when running on iOS 5 sim/device. But When I put a NSLog
call in front of CGContextAddPath
, it works correctly. And this is, because it's significantly slown down.
So the problem is in the frequency of -drawRect
callings. That's ok, I could fake it 'till I'd make it, but that's not the way professional works.
Therefore I'm asking why is this happening?
-(void)drawRect:(CGRect)r
{
// Get the graphics context and clear it
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, self.bounds);
[[UIColor whiteColor] set];
UIRectFill ([self bounds]);
// Draw every single section as a path
for (ShopSection *section in self.shopSectionsArray) {
// Draw the walls
[section.darkColor setFill];
for (MMPath *ppath in section.darkPathArray) {
CGContextAddPath(context,ppath.path);
CGContextDrawPath(context, kCGPathFill);
}
}
}
Edit: ARC enabled
MMPaths are not changing
EXC_BAD_ACCESS is responding to bad section object / dunno why (they're stored safely in the array)
Superview: UIScrollView Layer: CATiledLayer
The problem with bad access occurs when the content is rapidly redrawn - on fast device/simulator or when wildly scrolling and zooming.
Edit2: I think I got it! The problem is that CATiledLayer draws on backround threads, so it somehow catches it's tail. Have anyone an idea how to fix that? What is the best approach for that? What am I doing wrong?
Upvotes: 0
Views: 400
Reputation: 1915
I finally changed my mind and used the CAShapeLayer instead of my MMPath (NSObject with CGPath property). Then using CGRectIntersectsRect, I've managed to get rid of that multithreading bug. It also mean an optimalization as only the appropriate shapes are drawn in each rect.
So that's how multiple shapes in CATiledLayer shall be drawn:
-(void)drawRect:(CGRect)rect
{
// Get the graphics context and clear it
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, self.bounds);
[[UIColor whiteColor] set];
UIRectFill ([self bounds]);
// Draw every single section as a path
for (ShopSection *section in self.shopSectionsArray) {
CAShapeLayer *s = section.wallsShapeLayer;
// Draw the walls
if ( CGRectIntersectsRect(rect, s.frame ) )
{
// Rasterising before rendering enhances the performance a bit
s.shouldRasterize = YES;
[s renderInContext:context];
}
}
}
Upvotes: 0
Reputation: 299275
This loop is incorrect:
for (MMPath *ppath in section.darkPathArray) {
CGContextAddPath(context,ppath.path);
CGContextDrawPath(context, kCGPathFill);
}
CGContextAddPath()
adds to "the current path." CGContextDrawPath
draws "the current path." So you keep extending the path, then redrawing everything. You mean this:
for (ShopSection *section in self.shopSectionsArray) {
// Draw the walls
[section.darkColor setFill];
for (MMPath *ppath in section.darkPathArray) {
CGContextAddPath(context,ppath.path);
}
}
CGContextDrawPath(context, kCGPathFill);
Upvotes: 1