PDA

View Full Version : Retrieved CGPath shows as nil..




RottenApple2
Sep 20, 2012, 07:21 AM
I have a problem retrieving a previously created CGMutablePath. I create it in touchesBegan but then when I try to retrieve it with a function (GetLastPath) it shows as nil:

This is the error I get when I try to add the retrieved path to an NSMutableArray

"*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'CGPath must be non-nil".
Help please!

CGMutablePathRef cgPath;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//code

// Create a path
cgPath = CGPathCreateMutable();
CGPathAddEllipseInRect(cgPath, NULL, CGRectMake(0, 0, 300, 300));
CGPathAddEllipseInRect(cgPath, NULL, CGRectMake(50, 50, 200, 200));
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
//code
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
//code
}

-(CGMutablePathRef)GetLastPath
{
return cgPath;
}



chown33
Sep 20, 2012, 01:32 PM
Where you have //code in your posted code, is that the actual comment? Or does it indicate you've left code out of what you posted? If you've left code out, please post complete actual code.


Given the posted code, logic dictates that cgPath will be nil until after touchesBegan: is called at least once. So is that method being called at least once?


None of the posted code shows an NSMutableArray, or a call to GetLastPath. Post the actual code where the error occurs.

RottenApple2
Sep 21, 2012, 02:02 AM
Hi. [self GetLastPath] is called after touchesBegan, touchesMoved and touchesEnded are called (in this sequence). Where it says "//code" it means that I have left the code out as it is very long and (I think) irrelevant to the issue. I've added it anyway in case I have missed something.

CGMutablePathRef cgPath;
NSMutableArray *ARRAY;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

mouseSwiped = NO;
UITouch *touch = [touches anyObject];

currentPoint = [touch locationInView:self];
pointArray = nil;
pointArray=[[NSMutableArray alloc] init];
[bufferArray removeAllObjects];
previousPoint1 = [touch previousLocationInView:self];
previousPoint2 = [touch previousLocationInView:self];
lastPoint = [touch locationInView:self];
FirstPoint = lastPoint;

// Create the path data.
cgPath = CGPathCreateMutable();
CGPathAddEllipseInRect(cgPath, NULL, CGRectMake(0, 0, 300, 300));
CGPathAddEllipseInRect(cgPath, NULL, CGRectMake(50, 50, 200, 200));
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = YES;

UITouch *touch = [touches anyObject];
currentPoint = [touch locationInView:self];
previousPoint2 = previousPoint1;
previousPoint1 = [touch previousLocationInView:self];
mid1 = midPoint(previousPoint1, previousPoint2);
mid2 = midPoint(currentPoint, previousPoint1);
currentPoint = [touch locationInView:self];

[pointArray addObject: [NSValue valueWithCGPoint:previousPoint2]];
[pointArray addObject:[NSValue valueWithCGPoint:previousPoint1]];
[pointArray addObject:[NSValue valueWithCGPoint:currentPoint]];

_path = CGPathCreateMutable();
CGPathMoveToPoint(_path, NULL, mid1.x, mid1.y);
CGPathAddQuadCurveToPoint(_path, NULL, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
UIGraphicsBeginImageContext(self.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[drawImage.image drawInRect:CGRectMake(0, 0, drawImage.frame.size.width, drawImage.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
BrushSize = [[self retrieveBrushSizeFromUserDefaults] intValue];
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), BrushSize);
[self SetColor];
CGContextAddPath(context, _path);
CGContextStrokePath(context);
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

lastPoint = currentPoint;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

UITouch *touch = [touches anyObject];

CGPathRef pathToAdd = [self GetLastPath];
[ARRAY addObject:[UIBezierPath bezierPathWithCGPath: pathToAdd]];

//IT CRASHES HERE WITH ERROR
//*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'CGPath must be non-nil'
}

-(CGMutablePathRef)GetLastPath {return cgPath;}

chown33
Sep 21, 2012, 03:23 PM
Only two methods refer to cgPath. The touchesMoved: method doesn't refer to cgPath at all. It uses a _path variable you haven't shown.

Use the debugger to confirm your expectation that things are as they should be. Specifically, that touchesBegan: is called before any calls to touchesEnded:, and that cgPath is non-nil when touchesBegan: returns. You could also add NSLog statements to both the Began and Ended methods, to make sure they only occur in the correct sequence.

Debugging requires gathering evidence to confirm expectations or beliefs. "I expect X" or "I believe X" is not the same as "I have evidence of X". Gather the evidence of what's really happening and post it.

RottenApple2
Sep 22, 2012, 01:49 AM
chown, you are an absolute genius! Actually there was nothing wrong in the code posted but GetLastPath was being called in MainViewController's ViewDidLoad without me realising this, even before touchesBegan was called! That's why the path was still nil and it made the program crash when I was trying to add an empty path to the array. I would have never found this silly bug without some NSLog statements. Thank you!

KnightWRX
Sep 22, 2012, 07:56 AM
I would have never found this silly bug without some NSLog statements.

Actually, and this is not an issue only you have but many posters here do, yes you would have without NSLog statements.

The debugger, with its "step into, step over, watch variables" would have told you the same, probably much quicker and easier than just inserting a bunch of NSLog statements.

It is quite the useful tool and I don't know why it has fallen on the way side and people don't use it anymore. It was one of the first things I learned to use when I learned programming, and actually running the code line-by-line, checking variables change between execution of certain instructions, can point to these bugs in a matter of minutes rather than after hours of digging through the web and printing out a bunch of information to the console using NSLog.

A good tutorial :

http://www.youtube.com/watch?v=gPzSSeJc2oo

Take 10 minutes, learn this, it's going to be a great tool in the future for you.

Duncan C
Sep 22, 2012, 09:58 AM
Actually, and this is not an issue only you have but many posters here do, yes you would have without NSLog statements.

The debugger, with its "step into, step over, watch variables" would have told you the same, probably much quicker and easier than just inserting a bunch of NSLog statements.

It is quite the useful tool and I don't know why it has fallen on the way side and people don't use it anymore. It was one of the first things I learned to use when I learned programming, and actually running the code line-by-line, checking variables change between execution of certain instructions, can point to these bugs in a matter of minutes rather than after hours of digging through the web and printing out a bunch of information to the console using NSLog.

A good tutorial :

http://www.youtube.com/watch?v=gPzSSeJc2oo

Take 10 minutes, learn this, it's going to be a great tool in the future for you.

I heartily agree that the debugger is an invaluable tool for finding problems. I don't think it has "fallen by the wayside." Rather, I think that there are lots of people out there who just don't know how to use it.

Learning the debugger in any given development environment is crucial. If you can't debug your code, you will waste days, weeks, and more trying to figure out problems that would be easy to find if you knew how to use the tools.