Search code examples
xcodedebuggingbreakpoints

how to set "smart" breakpoint in Xcode when method returns a specific value?


I have a method which returns a bool value, with several exit points. However, it does not seem to work correctly, so I would like to set an automatic breakpoint to see when it returns a YES value, so I can check all the variables and calculations in the debugger. I would like to stop the debugger whenever a YES value is returned.

I have a similar smart breakpoint set for objc_exception_throw, so I know it's possible, I am just not sure how.


(In case it helps anyone, the way you can set the exception breakpoint: in the Breakpoints window (Run -> Show -> Breakpoints) enter objc_exception_throw as "Breakpoint", and libobjc.A.dylib as "Location")

EDIT: the specific code I would like to use it for:

- (BOOL)collisionOccured {
    // Assumption: helicopter is of square shape (collision calculated by radius), walls are rectangles
    // This approach is based on the solution seen here: http://stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection/402010#402010

    float helicopterImageWidth = [helicopter texture].contentSize.width;
    float wallImageWidth = [[walls lastObject] texture].contentSize.width;
    float wallImageHeight = [[walls lastObject] texture].contentSize.height;
    float helicopterCollisionRadius = helicopterImageWidth * 0.4f;

    CGPoint helicopterPosition = helicopter.position;


    int numWalls = [walls count];
    for (int i = 0; i < numWalls; i++) {
        CCSprite *wall = [walls objectAtIndex:i];

        if ([wall numberOfRunningActions] == 0) {
            // The wall is not moving, we can skip checking it.
            continue;
        }

        CGPoint wallPosition = wall.position;

        float helicopterDistanceX = abs(helicopterPosition.x - wallPosition.x - wallImageWidth/2);
        float helicopterDistanceY = abs(helicopterPosition.y - wallPosition.y - wallImageHeight/2);

        if (helicopterDistanceX > (wallImageWidth/2 + helicopterCollisionRadius)) { return NO; }
        if (helicopterDistanceY > (wallImageHeight/2 + helicopterCollisionRadius)) { return NO; }

        if (helicopterDistanceX <= (wallImageWidth/2)) { return YES; }
        if (helicopterDistanceY <= (wallImageHeight/2)) { return YES; }

        float cornerDistance_sq = powf((helicopterDistanceX - wallImageWidth/2), 2) + 
                                powf((helicopterDistanceY - wallImageHeight/2), 2);

        return (cornerDistance_sq <= powf(helicopterCollisionRadius, 2));
    }

    // this should not occur
    return NO;
}

This method is called via

- (void)update:(ccTime)delta {
    if ([self collisionOccured]) {
        NSLog(@"A collision occured");
    }
}

The problem is that the update method takes delta (time passed) as argument, so I can't check what's happening frame by frame -- whenever I continue the execution, I am presented with a different scene.

(I am using cocos2d in the code)


Solution

  • You can set conditional breakpoints. With a slight tweak to update:

    - (void)update:(ccTime)delta {
         BOOL collided = [self collisionOccured];
         if (collided) {
            NSLog(@"A collision occured");
        }
    }
    

    you can set a breakpoint as normal after the BOOL's assignment (i.e. on the if line), then right-click on the blue breakpoint arrow and select "Show Message Bubble", and add collided as the Condition. The extra variable should get optimized away in Release build mode.