2

I am having some problems with an app that keeps crashing intermittently. Code below is in a UIView with CATiledLayer as its backing layer:

- (UIBezierPath *)path
{
    if(_path == nil){

        _path = [UIBezierPath bezierPath];
        CGFloat lineWidth = 5;
        [_path setLineWidth:lineWidth];
        [_path setLineJoinStyle:kCGLineJoinRound];
        [_path setLineCapStyle:kCGLineCapRound];       

        [_path moveToPoint:CGPointMake(100, 100)];      
        [_path addLineToPoint:CGPointMake(200,200)];
        [_path addLineToPoint:CGPointMake(150,200)];
        [_path addLineToPoint:CGPointMake(50,400)];
        _path closePath];

        return _path;
    }    
return _path;
}

- (void)drawRect:(CGRect)rect
{  
    [[UIColor colorWithRed:0.1 green:0.1 blue:1 alpha:0.45] setStroke];//sets stroke color in current context
    [self.path stroke];
}

I get the following error code:

Single stepping until exit from function _ZN2CG4Path15apply_transformERK17CGAffineTransform, which has no line number information.

There doesn't seem to be any pattern to when the error occurs. It can seems to occur at some point doing scrolling or zooming. Sometimes in crashes as soon as I zoom/scroll. Sometimes I can zoom and scroll for a while until it crashes.

I know before iOS4 the UIKit was not thread safe and could not be used with CATiledLayers. See tech note My problem (i think) seems to be a thread issue. Surely UIKit can't be to blame?

GWed
  • 15,167
  • 5
  • 62
  • 99
  • What happens when you recalculate path every time and never store it on a variable (that may be non thread-safe)? – sch Feb 23 '12 at 23:37
  • That seems to have worked. Only problem is how would I pass a different path to my drawRect? My example has been trivialised for easy reading, but my programme needs to set the self.path property which then needs to be drawn – GWed Feb 24 '12 at 06:58

1 Answers1

4

Try to make the path property atomic.

Also, you should probably modify drawRect to the following:

- (void)drawRect:(CGRect)rect
{  
    [[UIColor colorWithRed:0.1 green:0.1 blue:1 alpha:0.45] setStroke];//sets stroke color in current context
    @synchronized(self) {
        [self.path stroke];
    }
}
sch
  • 27,436
  • 3
  • 68
  • 83
  • That looks like a good idea - thanks. Only issue now is that the problem seems to have gone away with my old implementation - this is really confusing. Ive tried various things to make the problem worse i.e. setting the number of CATiles to large numbers, which would mean that 1000s of threads are called to create the tiles, but that doesn't seem to trigger the error. Is there anyway you know for me to find the error exactly - it would be nice to know. I feel very nervous releasing an app with a lurking intermittent crash problem – GWed Feb 24 '12 at 09:58
  • @Gaz_Edge - The problem was solved with your original code verbatim, without any modifications? – sch Feb 24 '12 at 10:02
  • lol not quite - this morning the error had gone with the original code, but then came back again. So am now using @synchronized and since I haven't seen the problem once. Still, it is strange that when I tried to make the problem worse, I didn't see an error. Would be good to know for sure where the error was/is – GWed Feb 24 '12 at 10:33
  • My guess is that multiple threads are trying to access CGContext of the view and/or the path property at the same time. – sch Feb 24 '12 at 10:37
  • Yeah thats what i think too. Thats why I thought if I could get more threads to call the context and the path (i.e. set a small tile size 16,16), the error would be seen more frequently, but that doesn't seem to be the case. Anyway, for the last hour or so, using @synchronisation seems to have solved the problem - thanks! – GWed Feb 24 '12 at 11:00