1. Welcome to the new MacRumors forums. See our announcement and read our FAQ

recursive method question

Discussion in 'iPhone/iPad Programming' started by dashiell, Jul 31, 2011.

  1. macrumors newbie


    This is a 2 part question for a match 3 game I'm making.

    part 1:

    I want to run another method to remove the nodes not flagged connected after the following method flags nodes connected. The recursion does end, it's not stuck in an infinite loop.

    If I add a breakpoint after calling the flagConnectedWithIndex method (or NSLog), it is never reached.

    part 2:

    How can I free the memory allocated for the surroundingIndices pointer?

    -(void) flagConnectedWithIndex:(int)index
    	NSMutableArray *surroundingIndices = [self getSurroundingIndices:index];
    	for(NSNumber *num in surroundingIndices) {
    		int indexNum = [num intValue];
    		id obj = [arrayEnemyTargets_ objectAtIndex:indexNum];
    		if(obj != [NSNull null]) {
    			Enemytarget *t = obj;
    			if(!t.isDead && !t.connected) {
    				t.connected = YES;
    				//[t setOpacity:128];
    				[self flagConnectedWithIndex:t.index];
    Thanks a lot!
  2. macrumors 65816


    Put a breakpoint at the top of the method and step through it. What does execute? If surroundingIndices is too big for this to be practical, add lots of NSLog calls so you get running commentary on what parts of the method are executing and why.

    Send it release after the for loop?
  3. macrumors newbie

    Thanks for your reply, Jiminaus.

    Everything is executed within this. There is no point where it fails. The only problem is anything called after this method is not called.

    I can't release surroundingIndices after the for loop, as it will break recursion.
  4. macrumors 65816


    Assuming your not doing anything bizarre like setjmp/longjmp or stack hacking, the only reason I see for that would be if an exception is causing the stack to unwind.

    What do you mean by "it will break recursion"?
  5. macrumors 603

    How do you know the recursion ends? What evidence do you have that the recursion ends? You may believe it ends, but belief and evidence are two different things.

    The fact that it's not hitting the breakpoint seems like evidence that the recursion does NOT end. Or at least it doesn't end normally. If it did, then the breakpoint or NSLog() should be hit, and you'd have evidence that it ends.

    What happens if you put an NSLog() or breakpoint before the for loop? Does it hit that every time? At what point do those logs or breakpoints stop? If they ever stop, then that's evidence that the recursion has stopped. But if the breakpoint or NSLog() after the loop is never hit, then the likely explanation is that you have an exception, perhaps due to stack overflow.

    Post the code for getSurroundingIndices: . Maybe it's not returning.

    If getSurroundingIndices: is following the Cocoa naming rule for ownership of returned objects, then its returned NSMutableArray will not be owned by the calling method (flagConnectedWithIndex:). That means getSurroundingIndices: will already have called -autorelease, or done something else to account for the memory of the returned array. Which then means that flagConnectedWithIndex: should do nothing to free the memory for its surroundingIndices object.

    If you're not following the Cocoa naming rule, you should be.
  6. macrumors newbie


    Thanks chown & jiminaus.

    If I autorelease the indices array in getSurroundingIndices on return, it breaks.

    I tryed logging as you posted, thanks.

    	NSMutableArray *indices = [NSMutableArray arrayWithCapacity:6];
    	int bottomLeft,bottomRight,topLeft,topRight, left, right;
    	if(index/Grid_Num_H %2 == 0) {
    		if(index %Grid_Num_H != 0) {
    			left = index - 1;								
    			bottomLeft = index - Grid_Num_H -1;				
    			topLeft = index + Grid_Num_H -1;				
    			[indices addObject:[NSNumber numberWithInt:left]];
    			[indices addObject:[NSNumber numberWithInt:bottomLeft]];
    			[indices addObject:[NSNumber numberWithInt:topLeft]];
    		right = index +1; 				
    		bottomRight = index - Grid_Num_H;					
    		topRight = index + Grid_Num_H;			
    		if(index % Grid_Num_H != 8)
    			[indices addObject:[NSNumber numberWithInt:right]];
    		[indices addObject:[NSNumber numberWithInt:bottomRight]];
    		[indices addObject:[NSNumber numberWithInt:topRight]];
    	else {
    		bottomLeft = index - Grid_Num_H;					
    		left = index - 1;									
    		topLeft = index + Grid_Num_H;						
    		[indices addObject:[NSNumber numberWithInt:bottomLeft]];
    		if(index % Grid_Num_H != 0)
    			[indices addObject:[NSNumber numberWithInt:left]];
    		[indices addObject:[NSNumber numberWithInt:topLeft]];
    		if(index % Grid_Num_H != 8) {
    			right = index + 1;								
    			bottomRight = index - Grid_Num_H +1;			
    			topRight = index + Grid_Num_H + 1;		
    			[indices addObject:[NSNumber numberWithInt:right]];
    			[indices addObject:[NSNumber numberWithInt:bottomRight]];
    			[indices addObject:[NSNumber numberWithInt:topRight]];
    	return indices;
  7. macrumors 65816


    Because you used a convenience constructor (arrayWithCapacity:) instead of alloc/initWithCapacity, you don't own the array. Therefore you should send neither release nor autorelease, unless of course you retain it at some point.
  8. dashiell, Jul 31, 2011
    Last edited by a moderator: Jul 31, 2011

    macrumors newbie

    -Ah, thank you.
  9. macrumors 6502a

    If you are using Xcode 4, this isn't necessary. Add your breakpoint, then right click on it and select Edit Breakpoint. You can change the breakpoint to simply log and continue; no need to litter your code with NSLog statements.

    Wait, how is getSurroundingIndices: defined? It probably returns an autoreleased array and doesn't need releasing.
  10. macrumors 65816


    Nice tip.

    Yes, we determined that. I had confused the significance of a -get<property> accessor verses a -property accessor. I was think it was ownership verses non-ownership. But it's result passed by reference verses result passed by value. Now, I'm certain the OP isn't aware of this subtly and has just incorrectly named the method.

Share This Page